import os
import sys
import subprocess
import time
import datetime
from typing import Tuple, Optional, List

# --- 1. CONFIGURATION ---
DEFAULT_API_URL = "https://b22q73wp50.execute-api.us-east-1.amazonaws.com/dev"
ORIGINAL_PLAYGROUND_URL = "https://bhtrtkrbf4.execute-api.us-east-1.amazonaws.com/prod/m"
TABLE_ID = "sustainabilitymc"
FALLBACK_TABLE_ID = "sustainabilitymcfallback"
TOTAL_COURSE_TASKS = 10 # Sync with Act6 + Act7
LOCAL_TEST_SESSION_ID = None


# --- Team Name Translations ---
TEAM_NAME_TRANSLATIONS = {
    "ca": {
        "The Climate Guardians": "Els Guardians del Clima",
        "United Eco-Architects": "Eco-Arquitectes Units",
        "The Energy Detectives": "Els Detectius de l'Energia",
        "The Sustainability League": "La Lliga de la Sostenibilitat",
        "Green Future Engineers": "Enginyers del Futur Verd",
        "Zero Carbon Avengers": "Els Venjadors del Carboni Zero",
    },
}
UI_TEAM_LANG = "ca"


def translate_team_name_for_display(english_name: str, lang: str = "ca") -> str:
    return TEAM_NAME_TRANSLATIONS.get(lang, {}).get(english_name, english_name)

# ==============================================================================
# --- BRANDING CONFIGURATION ---
SHOW_BRANDED_LOGOS = True

# PASTE YOUR SINGLE BANNER BASE64 STRING HERE (do not include "data:image/jpeg;base64," prefix)
BRAND_BANNER_BASE64 = """[encoded data, 1026988 characters]"""

# Fallback/Default Logos
FAKE_LOGO_1 = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/IBM_logo.svg/200px-IBM_logo.svg.png" 
FAKE_LOGO_2 = "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/University_of_California%2C_Berkeley_logo.svg/200px-University_of_California%2C_Berkeley_logo.svg.png" 
FAKE_LOGO_3 = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Apple_logo_black.svg/150px-Apple_logo_black.svg.png" 
# ==============================================================================

# --- 2. SETUP & DEPENDENCIES ---
def install_dependencies():
    packages = ["gradio>=5.0.0", "aimodelshare", "pandas"]
    for package in packages:
        subprocess.check_call([sys.executable, "-m", "pip", "install", package])

try:
    import gradio as gr
    import pandas as pd
    from aimodelshare.playground import Competition
    from aimodelshare.moral_compass import MoralcompassApiClient
    from aimodelshare.aws import get_token_from_session, _get_username_from_token
except ImportError:
    print("📦 Instal·lant dependències...")
    install_dependencies()
    import gradio as gr
    import pandas as pd
    from aimodelshare.playground import Competition
    from aimodelshare.moral_compass import MoralcompassApiClient
    from aimodelshare.aws import get_token_from_session, _get_username_from_token

# --- 3. AUTH & HISTORY HELPERS ---
def _try_session_based_auth(request: "gr.Request") -> Tuple[bool, Optional[str], Optional[str]]:
    try:
        session_id = request.query_params.get("sessionid") if request else None
        if not session_id and LOCAL_TEST_SESSION_ID:
            session_id = LOCAL_TEST_SESSION_ID
        if not session_id:
            return False, None, None
        token = get_token_from_session(session_id)
        if not token:
            return False, None, None
        username = _get_username_from_token(token)
        if not username:
            return False, None, None
        return True, username, token
    except Exception:
        return False, None, None

def fetch_user_history(username, token):
    default_acc = 0.0
    default_team = "Team-Unassigned"
    try:
        playground = Competition(ORIGINAL_PLAYGROUND_URL)
        df = playground.get_leaderboard(token=token)
        if df is None or df.empty:
            return default_acc, default_team
        if "username" in df.columns and "accuracy" in df.columns:
            user_rows = df[df["username"] == username]
            if not user_rows.empty:
                best_acc = user_rows["accuracy"].max()
                if "timestamp" in user_rows.columns and "Team" in user_rows.columns:
                    try:
                        user_rows = user_rows.copy()
                        user_rows["timestamp"] = pd.to_datetime(
                            user_rows["timestamp"], errors="coerce"
                        )
                        user_rows = user_rows.sort_values("timestamp", ascending=False)
                        found_team = user_rows.iloc[0]["Team"]
                        if pd.notna(found_team) and str(found_team).strip():
                            default_team = str(found_team).strip()
                    except Exception:
                        pass
                return float(best_acc), default_team
    except Exception:
        pass
    return default_acc, default_team

# --- 4. CSS (UPDATED FOR DARK/LIGHT MODE) ---
# --- 4. CSS (FIXED TABS & DARK MODE) ---
css = """
/* --- CONTAINER STYLES --- */
.summary-box { 
    background: var(--block-background-fill); 
    padding: 20px; 
    border-radius: 12px; 
    border: 1px solid var(--border-color-primary); 
    margin-bottom: 20px; 
    box-shadow: var(--block-shadow); 
}

.scenario-box { 
    padding: 24px; 
    border-radius: 14px; 
    background: var(--block-background-fill); 
    border: 1px solid var(--border-color-primary); 
    margin-bottom: 22px; 
    box-shadow: var(--block-shadow); 
    color: var(--body-text-color); 
}

/* --- TYPOGRAPHY --- */
.slide-title { 
    margin-top: 0; 
    font-size: 1.9rem; 
    font-weight: 800; 
    color: var(--body-text-color); 
}
.slide-body { 
    font-size: 1.12rem; 
    line-height: 1.65; 
    color: var(--body-text-color);
}

/* --- LEADERBOARD & TABLES --- */
.table-container { 
    height: 320px; 
    overflow-y: auto; 
    border: 1px solid var(--border-color-primary); 
    border-radius: 10px; 
    background: var(--background-fill-primary);
}
.leaderboard-table { 
    width: 100%; 
    border-collapse: collapse; 
    color: var(--body-text-color);
}
.leaderboard-table th { 
    position: sticky; 
    top: 0; 
    background: var(--background-fill-secondary); 
    padding: 10px; 
    text-align: left; 
    border-bottom: 2px solid var(--border-color-primary); 
    font-weight: 800; 
    color: var(--body-text-color);
}
.leaderboard-table td { 
    padding: 10px; 
    border-bottom: 1px solid var(--border-color-primary); 
    color: var(--body-text-color);
}

/* Highlighting Rows */
.row-highlight-me { background: color-mix(in srgb, var(--color-accent) 20%, transparent); font-weight: 700; }
.row-highlight-team { background: color-mix(in srgb, var(--color-accent) 10%, transparent); font-weight: 700; }

/* --- TAB LOGIC (RESTORED) --- */
.leaderboard-card input[type="radio"] { display: none; }

.lb-tab-label { 
    display: inline-block; 
    padding: 8px 16px; 
    margin-right: 8px; 
    border-radius: 20px; 
    cursor: pointer; 
    border: 1px solid var(--border-color-primary); 
    font-weight: 700; 
    font-size: 0.94rem; 
    color: var(--body-text-color);
    background: var(--background-fill-primary);
}

/* Active Tab Style */
#lb-tab-team:checked + label, #lb-tab-user:checked + label { 
    background: var(--color-accent); 
    color: white; 
    border-color: var(--color-accent); 
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

/* Panel Hiding/Showing Logic */
.lb-panel { display: none; margin-top: 15px; } /* Hide both by default */

#lb-tab-team:checked ~ .lb-tab-panels .panel-team { display: block; } /* Show Team if Team checked */
#lb-tab-user:checked ~ .lb-tab-panels .panel-user { display: block; } /* Show User if User checked */

/* --- UTILITY BOXES --- */
.ai-risk-container { 
    margin-top: 16px; 
    padding: 16px; 
    background: var(--background-fill-secondary); 
    border-radius: 10px; 
    border: 1px solid var(--border-color-primary); 
}

/* --- BUTTONS --- */
.share-btn { 
    display: inline-flex; 
    align-items: center; 
    justify-content: center; 
    gap: 8px; 
    padding: 10px 20px; 
    border-radius: 50px; 
    font-weight: 700; 
    text-decoration: none; 
    color: white !important;
    border: none; 
    cursor: pointer;
}
.share-print { background-color: var(--color-accent, #1e3a8a); }

/* --- PRINT ONLY --- */
@media print {
    body, body * { visibility: hidden !important; height: 0; overflow: hidden; }
    #cert-printable, #cert-printable * { visibility: visible !important; height: auto; overflow: visible; }
    #cert-printable { position: absolute !important; left: 0 !important; top: 0 !important; width: 100% !important; z-index: 999999; }
}
"""

# --- 5. RENDERERS (PORTED FROM APP 2) ---

# --- 5. RENDERERS (UPDATED FOR DARK MODE) ---

def render_top_dashboard(data):
    display_score = 0.0
    rank_display = "–"
    team_rank_display = "–"
    
    if data:
        display_score = float(data.get("score", 0.0))
        rank_display = f"#{data.get('rank', '–')}"
        team_rank_display = f"#{data.get('team_rank', '–')}"
    
    return f"""
    <div class="summary-box" style="text-align:center; padding: 30px; max-width: 800px; margin: 0 auto 20px auto; background: var(--block-background-fill);">
        
        <div style="border-bottom: 2px solid var(--border-color-primary); padding-bottom: 20px; margin-bottom: 25px;">
            <h3 style="margin:0; color: var(--color-accent); font-size: 1.3rem; text-transform: uppercase; letter-spacing: 2px; font-weight: 800;">
                🎉 Certificació completada 🎉
            </h3>
        </div>

        <div style="background: var(--background-fill-secondary); border-radius: 16px; border: 1px solid var(--border-color-primary); padding: 30px; margin-bottom: 20px;">
            <div class="label-text" style="color: var(--body-text-color-subdued); font-size: 1.0rem; margin-bottom: 10px;">Puntuació Final del Compàs Moral</div>
            <div style="font-size: 4.5rem; font-weight: 800; color: var(--color-primary); line-height: 1;">
                {display_score:.3f}
            </div>
             <div style="font-size: 0.9rem; color: var(--body-text-color-subdued); margin-top: 5px;">(Escala: 0,0 - 1,0)</div>
        </div>

        <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
            <div style="background: var(--background-fill-primary); border: 1px solid var(--border-color-primary); border-radius: 12px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;">
                <div class="label-text" style="color: var(--body-text-color-subdued); font-size: 0.85rem; margin-bottom: 5px;">Classificació de l'Equip</div>
                <div class="score-text-team" style="font-size: 2.0rem; margin: 0;">{team_rank_display}</div>
            </div>

            <div style="background: var(--background-fill-primary); border: 1px solid var(--border-color-primary); border-radius: 12px; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;">
                <div class="label-text" style="color: var(--body-text-color-subdued); font-size: 0.85rem; margin-bottom: 5px;">Classificació Global</div>
                <div class="score-text-global" style="font-size: 2.0rem; margin: 0; color: var(--body-text-color);">{rank_display}</div>
            </div>
        </div>

        <div style="margin-top: 30px;">
            <span style="background-color: rgba(16, 185, 129, 0.15); color: var(--color-accent); padding: 10px 24px; border-radius: 99px; font-weight: 700; font-size: 0.95rem; border: 1px solid var(--color-accent); display: inline-flex; align-items: center; gap: 8px;">
                ✅ Certificat oficial preparat
            </span>
        </div>

    </div>
    """

def render_leaderboard_card(data, username, team_name):
    # This remains mostly the same, ensuring consistency with previous apps
    team_rows = ""
    user_rows = ""
    
    if data and data.get("all_teams"):
        for i, t in enumerate(data["all_teams"]):
            # Highlight the user's team
            cls = "row-highlight-team" if t["team"] == team_name else "row-normal"
            team_rows += (
                f"<tr class='{cls}'><td style='padding:8px;text-align:center;'>{i+1}</td>"
                f"<td style='padding:8px;'>{translate_team_name_for_display(t['team'], UI_TEAM_LANG)}</td>"
                f"<td style='padding:8px;text-align:right;'>{t['avg']:.3f}</td></tr>"
            )

    if data and data.get("all_users"):
        for i, u in enumerate(data["all_users"]):
            # Highlight the current user
            cls = "row-highlight-me" if u.get("username") == username else "row-normal"
            
            # Ensure the score in the table matches the 'official' final score
            sc = float(u.get("moralCompassScore", 0))
            if u.get("username") == username and data.get("score") != sc:
                sc = data.get("score")
                
            user_rows += (
                f"<tr class='{cls}'><td style='padding:8px;text-align:center;'>{i+1}</td>"
                f"<td style='padding:8px;'>{u.get('username','')}</td>"
                f"<td style='padding:8px;text-align:right;'>{sc:.3f}</td></tr>"
            )

    return f"""
    <div class="scenario-box leaderboard-card">
        <h3 class="slide-title" style="margin-bottom:10px;">📊 Classificació Final</h3>
        <div class="lb-tabs">
            <input type="radio" id="lb-tab-team" name="lb-tabs" checked>
            <label for="lb-tab-team" class="lb-tab-label">🏆 Equip</label>
            <input type="radio" id="lb-tab-user" name="lb-tabs">
            <label for="lb-tab-user" class="lb-tab-label">👤 Individual</label>
            <div class="lb-tab-panels">
                <div class="lb-panel panel-team">
                    <div class='table-container'>
                        <table class='leaderboard-table'>
                            <thead>
                                <tr><th>Posició</th><th>Equip</th><th style='text-align:right;'>Mitjana 🧭</th></tr>
                            </thead>
                            <tbody>{team_rows}</tbody>
                        </table>
                    </div>
                </div>
                <div class="lb-panel panel-user">
                    <div class='table-container'>
                        <table class='leaderboard-table'>
                            <thead>
                                <tr><th>Posició</th><th>Participant</th><th style='text-align:right;'>Puntuació 🧭</th></tr>
                            </thead>
                            <tbody>{user_rows}</tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
    """

# --- 6. HTML CERTIFICATE GENERATOR (SINGLE BANNER) ---
# --- 6. HTML CERTIFICATE GENERATOR (FIXED FOR DARK MODE) ---
# --- 6. HTML CERTIFICATE GENERATOR (STRICT COLOR ENFORCEMENT) ---
def generate_html_certificate(name, score, team_name):
    date_str = datetime.date.today().strftime("%B %d, %Y")
    cert_id = int(time.time())

    # BRAND COLORS
    c_primary = "#5a46cc"    # Deep Indigo
    c_sec_light = "#d0d5e9"  # Soft Lavender
    c_slate = "#8485a1"      # Tech Slate
    c_dark = "#1e293b"       # Dark Slate (Almost Black)
    c_black = "#000000"

    # --- LOGO LOGIC ---
    if SHOW_BRANDED_LOGOS:
        logo_section = f"""
        <div style="display: flex; justify-content: center; align-items: center; margin-top: 15px;">
             <img src="data:image/jpeg;base64,{BRAND_BANNER_BASE64}" style="height: 60px; width: auto; max-width: 100%; object-fit: contain;">
        </div>
        """
    else:
        logo_section = f"""
        <div style="display: flex; gap: 25px; opacity: 1.0; align-items: center; justify-content: center;">
             <img src="{FAKE_LOGO_1}" style="height: 30px; object-fit: contain;">
             <img src="{FAKE_LOGO_2}" style="height: 35px; object-fit: contain;">
             <img src="{FAKE_LOGO_3}" style="height: 25px; object-fit: contain;">
        </div>
        """

    # --- HTML STRUCTURE ---
    # Key Fix: Added 'color-scheme: light' to tell browser not to invert colors
    # Key Fix: Added specific color styles to EVERY text element (p, h2, h3, div, span, strong)
    html = f"""
    <div id="cert-printable" style="
        position: relative; width: 100%; max-width: 900px; margin: 0 auto;
        padding: 0;
        background-color: #ffffff !important;
        color-scheme: light !important; 
        border: 10px solid {c_primary};
        outline: 2px solid {c_primary}; outline-offset: -16px;
        font-family: 'IBM Plex Sans', 'Helvetica', sans-serif;
        color: {c_dark} !important;
        box-shadow: 0 15px 40px rgba(0,0,0,0.15);
        text-align: center;
        box-sizing: border-box;
    ">
        <div style="padding: 60px 50px;">

            <div style="display: flex; justify-content: space-between; align-items: flex-end; border-bottom: 2px solid {c_sec_light}; padding-bottom: 20px; margin-bottom: 40px;">
                <div style="text-align: left;">
                    <div style="
                        font-family: 'Source Serif Pro', 'Georgia', serif;
                        font-weight: 700;
                        color: {c_primary} !important;
                        font-size: 1.4rem;
                        letter-spacing: -0.5px;
                    ">
                        Iniciativa d'IA Verda - Programa d'Educació Digital
                    </div>
                    <div style="font-size: 0.75rem; color: {c_slate} !important; text-transform: uppercase; letter-spacing: 1.5px; margin-top: 5px;">
                        IA Sostenible - Acreditació de Responsabilitat Mediambiental
                    </div>
                </div>
                <div style="text-align: right;">
                    <div style="font-family: 'Courier New', monospace; font-size: 0.85rem; color: {c_slate} !important;">
                        REF_ID: <span style="color: {c_black} !important;">{cert_id}</span>
                    </div>
                </div>
            </div>

            <div style="margin-bottom: 40px;">
                <h3 style="
                    font-size: 1rem;
                    font-weight: 600;
                    color: {c_slate} !important;
                    text-transform: uppercase;
                    letter-spacing: 3px;
                    margin: 0;
                ">Certificació de la Iniciativa d'IA Verda</h3>

                <h3 style="
                    font-family: 'Source Serif Pro', 'Georgia', serif;
                    font-size: 3.5rem;
                    color: {c_dark} !important;
                    margin: 10px 0 0 0;
                    line-height: 1.1;
                ">
                    Innovació en IA Sostenible<br><span style="color: {c_primary} !important;">Gestió Mediambiental</span>
                </h3>
            </div>

            <div style="background: #f8fafc; padding: 30px; border-radius: 8px; border-left: 6px solid {c_primary}; margin-bottom: 40px; text-align: left;">
                <p style="font-size: 0.9rem; color: {c_slate} !important; text-transform: uppercase; margin: 0 0 5px 0;">Atorgat a l'enginyer/a d'IA Verda</p>
                <h2 style="
                    font-family: 'Source Serif Pro', 'Georgia', serif;
                    font-size: 3rem;
                    margin: 0;
                    color: {c_dark} !important;
                    font-weight: 700;
                ">{name}</h2>
                <p style="font-size: 1.1rem; color: {c_dark} !important; margin: 5px 0 0 0;">
                    Membre de <strong style="color: {c_dark} !important;">{translate_team_name_for_display(team_name, UI_TEAM_LANG)}</strong>
                </p>
            </div>

            <p style="font-size: 1.1rem; line-height: 1.6; color: {c_dark} !important; margin-bottom: 40px; text-align: left;">
                Aquest certificat acredita la capacitat d'aplicar la IA de manera sostenible i responsable. La persona titular ha auditat el consum energ&egrave;tic de sistemes d'IA, ha optimitzat l'&uacute;s i la selecci&oacute; de models, i ha avaluat la infraestructura per reduir-ne l'impacte ambiental.
            </p>

            <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 50px;">
                <div style="border: 1px solid {c_sec_light}; border-radius: 6px; padding: 15px; text-align: left;">
                    <div style="font-size: 0.75rem; color: {c_slate} !important; text-transform: uppercase; font-weight: 700;">Puntuació del Compàs Moral</div>
                    <div style="font-size: 2rem; font-weight: 700; color: {c_primary} !important; font-family: 'Courier New', monospace;">
                        {score:.3f}
                    </div>
                </div>
                <div style="border: 1px solid {c_sec_light}; border-radius: 6px; padding: 15px; text-align: left; background: #f0fdf4;">
                    <div style="font-size: 0.75rem; color: #166534 !important; text-transform: uppercase; font-weight: 700;">Estat de l'Auditoria</div>
                    <div style="font-size: 1.2rem; font-weight: 700; color: #15803d !important; margin-top: 8px;">
                        ✅ VERIFICAT VERD
                    </div>
                </div>
            </div>

            <div style="border-top: 2px solid {c_dark}; padding-top: 25px; display: flex; justify-content: space-between; align-items: flex-end;">
                <div style="text-align: left;">
                    <div style="font-family: 'Source Serif Pro', serif; font-size: 1.2rem; font-weight: 700; color: {c_black} !important;">
                        Iniciativa d'IA Verda
                    </div>
                    <div style="font-size: 0.85rem; color: {c_slate} !important; margin-top: 5px;">
                       {date_str}
                    </div>
                </div>

                {logo_section}

            </div>

        </div>
    </div>
    """
    return html

# --- 7. MODULE DEFINITIONS ---
MODULES = [
    # --- MODULE 0: VICTORY DASHBOARD ---
# --- MODULE 0: VICTORY DASHBOARD ---
    {
        "id": 0,
        "title": "Assoliment desbloquejat",
        "html": """
            <div class="scenario-box">
                <div class="slide-body">
                    <div style="text-align:center; margin-bottom:20px;">
                        <div style="font-size:3rem;">🏆</div>
                        <h2 class="slide-title" style="margin-top:5px; color:var(--color-primary);">
                            Assoliment desbloquejat
                        </h2>
                        <p style="font-size:1.1rem; max-width:800px; margin:0 auto; color: var(--body-text-color);">
                            Has completat amb èxit el protocol d'IA Verda.
                            <br>
                            Revisa les teves mètriques de rendiment finals a continuació abans de reclamar la teva credencial.
                        </p>
                    </div>

                    <div id="final-dashboard-inject"></div>
                    
                    <div style="text-align:center; margin-top:35px; padding:20px; background: var(--background-fill-secondary); border-radius:12px; border:2px solid var(--color-accent);">
                        <p style="font-size:1.15rem; font-weight:800; color:var(--color-accent); margin-bottom:5px;">
                            🚀 REP LA TEVA CERTIFICACIÓ ABANS DE LA COMPETICIÓ FINAL
                        </p>
                        <p style="font-size:1.05rem; margin:0; color: var(--body-text-color);">
                           Fes clic a <strong>Següent</strong> per revisar el teu registre d'enginyeria i generar el teu certificat.
                        </p>
                    </div> 
                </div>
            </div>
        """
    },
    # --- MODULE 1: THE ENGINEERING LOG ---
    {
        "id": 1,
        "title": "Registre d'enginyeria",
        "html": """
            <div class="scenario-box">
                <div class="slide-body">
                    <h2 class="slide-title" style="text-align:center;">📋 El teu curr&iacute;culum com a enginyer/a d'IA</h2>
                    <p style="text-align:center; margin-bottom:20px; opacity: 0.9;">
                        Has passat de veure la IA com una c&agrave;rrega ambiental a convertir-la en una tecnologia m&eacute;s sostenible. Enhorabona! Aix&ograve; &eacute;s el que has aconseguit millorar:
                    </p>

                    <div style="display:grid; gap:15px;">
                        <div style="background: rgba(59, 130, 246, 0.1); border-left:5px solid #3b82f6; padding:15px; border-radius:4px;">
                            <div style="font-weight:800; color:#3b82f6; font-size:1.1rem;">⚡ CONSCI&Egrave;NCIA ENERG&Egrave;TICA</div>
                            <div style="opacity: 0.9;">Has descobert els costos energ&egrave;tics ocults de la IA, des de la pregunta que escrius fins als ordinadors gegants que la processen. Ara saps que generar una sola imatge pot consumir l'equivalent a mitja c&agrave;rrega de m&ograve;bil, i que fer 25 consultes pot evaporar una ampolla d'aigua.</div>
                        </div>

                        <div style="background: rgba(139, 92, 246, 0.1); border-left:5px solid #8b5cf6; padding:15px; border-radius:4px;">
                            <div style="font-weight:800; color:#8b5cf6; font-size:1.1rem;">✂️ OPTIMITZACI&Oacute; I EFICI&Egrave;NCIA</div>
                            <div style="opacity: 0.9;">Has apr&egrave;s a formular millor les teves preguntes i a triar el model adequat per reduir el malbaratament energ&egrave;tic en m&eacute;s d'un 60%, sense perdre qualitat en els resultats.</div>
                        </div>

                        <div style="background: rgba(16, 185, 129, 0.1); border-left:5px solid #10b981; padding:15px; border-radius:4px;">
                            <div style="font-weight:800; color:#10b981; font-size:1.1rem;">🌍 INTEL&middot;LIG&Egrave;NCIA D'INFRAESTRUCTURA</div>
                            <div style="opacity: 0.9;">Has analitzat com es refreden els centres de dades, qu&egrave; hi ha darrere de les promeses d'energia renovable i com aquests sistemes impacten la xarxa el&egrave;ctrica de diferents pa&iuml;sos.</div>
                        </div>
                    </div>

                    <div style="text-align:center; margin-top:25px;">
                        <p style="font-size:1.0rem;">
                            Fes clic a <strong>Següent ▶️</strong> per generar el teu certificat oficial.
                        </p>
                    </div>
                </div>
            </div>
        """
    },
    # --- MODULE 2: CERTIFICATE GENERATOR ---
    {
        "id": 2,
        "title": "Certificació oficial",
        "html": """
            <div class="scenario-box">
                <div class="slide-body">
                    <h2 class="slide-title" style="text-align:center; color: var(--color-primary);">🎓 Reclama les teves credencials</h2>
                    <p style="text-align:center; margin-bottom:20px; color: var(--body-text-color);">
                        Introdueix el teu nom exactament com vols que aparegui al teu certificat oficial de la <strong>Iniciativa d'IA Verda</strong>.
                    </p>

                    <div style="background: rgba(22, 101, 52, 0.15); border:1px solid rgba(22, 101, 52, 0.3); padding:20px; border-radius:12px; text-align:center; margin-bottom:20px;">
                        <div style="font-weight:700; color: var(--color-primary); margin-bottom:10px;">AUTORITZAT PER A:</div>
                        <div style="font-size:1.5rem; font-weight:900; color: var(--color-primary); margin-bottom:5px;">ENGINYER/A D'IA VERDA</div>
                        <p style="font-size:0.9rem; color: var(--body-text-color); margin:0;">
                            Aquest document certifica que has adquirit coneixements en IA sostenible.
                        </p>
                    </div>
                </div>
            </div>
        """
    },
    # --- MODULE 3: THE FINAL TRANSITION ---
    {
        "id": 3,
        "title": "El desafiament final",
        "html": """
            <div class="scenario-box">
                <div class="slide-body">
                    <div style="text-align:center;">
                        <div style="font-size:3rem;">🚀</div>
                        <h2 class="slide-title" style="margin-top:10px;">La frontera final</h2>
                    </div>

                    <p style="font-size:1.1rem; text-align:center; max-width:800px; margin:0 auto 25px auto; opacity: 0.9;">
                        Tens el coneixement. Tens el certificat.
                        <br>
                        Ara, és el moment de demostrar que tens l'<strong>Habilitat</strong>.
                    </p>

                    <div class="ai-risk-container" style="background: var(--background-fill-secondary); border: 2px solid var(--color-primary);">
                        <h3 style="margin-top:0; color: var(--color-primary);">🏆 La competició de precisió</h3>
                        <p style="font-size:1.05rem; line-height:1.5; opacity: 0.9;">
                            La teva missió final és competir contra els teus companys per construir el <strong>model més precís possible</strong>.
                            <br><br>
                            Però recorda: <strong>Has de mantenir el teu Compàs Moral.</strong>
                        </p>
                    </div>

                    <div style="text-align:center; margin-top:30px;">
                      <p style="font-size:0.95rem; color:var(--body-text-color-subdued); margin-top:10px;">
                        <strong>Continua amb la següent activitat a continuació</strong> — o fes clic a
                        <span style="white-space:nowrap;">Següent (barra superior)</span> en vista expandida ➡️
                      </p>
                    </div>
                </div>
            </div>
        """
    }
]

# --- 8. LOGIC FUNCTIONS ---

def get_leaderboard_data(client, username, team_name):
    # Ported from App 2 logic
    try:
        resp = client.list_users(table_id=TABLE_ID, limit=500)
        users = resp.get("users", [])

        users_sorted = sorted(
            users, key=lambda x: float(x.get("moralCompassScore", 0) or 0), reverse=True
        )
        my_user = next((u for u in users_sorted if u.get("username") == username), None)
        score = float(my_user.get("moralCompassScore", 0) or 0) if my_user else 0.0
        rank = users_sorted.index(my_user) + 1 if my_user else 0
        completed_task_ids = my_user.get("completedTaskIds", []) if my_user else []

        team_map = {}
        for u in users:
            t = u.get("teamName")
            s = float(u.get("moralCompassScore", 0) or 0)
            if t:
                if t not in team_map: team_map[t] = {"sum": 0, "count": 0}
                team_map[t]["sum"] += s
                team_map[t]["count"] += 1
        teams_sorted = []
        for t, d in team_map.items():
            teams_sorted.append({"team": t, "avg": d["sum"] / d["count"]})
        teams_sorted.sort(key=lambda x: x["avg"], reverse=True)
        my_team = next((t for t in teams_sorted if t["team"] == team_name), None)
        team_rank = teams_sorted.index(my_team) + 1 if my_team else 0

        return {
            "score": score,
            "rank": rank,
            "team_rank": team_rank,
            "completed_task_ids": completed_task_ids,
            "all_users": users_sorted,
            "all_teams": teams_sorted
        }
    except:
        return None

def create_cert_handler(user_input_name, username_state, token, team_name):
    if not user_input_name:
        user_input_name = username_state

    os.environ["MORAL_COMPASS_API_BASE_URL"] = DEFAULT_API_URL
    client = MoralcompassApiClient(api_base_url=DEFAULT_API_URL, auth_token=token)
    data = get_leaderboard_data(client, username_state, team_name)
    score = data.get("score", 0.0)

    # Generate HTML content
    cert_html = generate_html_certificate(user_input_name, score, team_name)

    share_text = f"Acabo de certificar-me com a Enginyer/a d'IA Verda! 🌱 #IAVerda #IASostenible"
    # (Links omitted for brevity, they remain the same)
    
    # --- JAVASCRIPT POPUP PRINTER ---
    js_print_logic = """
    var cert = document.getElementById('cert-printable');
    var w = window.open('', '_blank');
    w.document.write('<!DOCTYPE html><html><head><title>Certificat</title>');
    w.document.write('<style>@page { size: landscape; margin: 0; } body { margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; height: 100vh; width: 100vw; overflow: hidden; } * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; } #cert-printable { width: 100%; max-width: 100%; height: auto; max-height: 100vh; object-fit: contain; }</style></head><body>');
    w.document.write(cert.outerHTML);
    w.document.write('</body></html>');
    w.document.close();
    setTimeout(function() { w.focus(); w.print(); w.close(); }, 500);
    """

    # --- UPDATED SHARE HTML FOR DARK/LIGHT MODE ---
    share_html = f"""
    <div style="margin-top:25px; text-align:center; padding:20px; background: var(--background-fill-secondary); border-radius:12px; border:1px solid var(--border-color-primary);">
        <p style="font-weight:800; color: var(--body-text-color); margin-bottom:15px; font-size:1.1rem;">
            📢 Desa i Comparteix el Teu Èxit
        </p>

        <div style="display:flex; justify-content:center; gap:12px; flex-wrap:wrap;">
            <button onclick="{js_print_logic}" class="share-btn share-print">🖨️ Imprimir / Desar com a PDF</button>
        </div>

        <p style="font-size:0.85rem; color: var(--body-text-color-subdued); margin-top:15px; font-style:italic;">
            📸 <strong>Consell:</strong> Fes clic a 'Imprimir' i tria 'Desar com a PDF' per conservar el teu certificat per sempre.
            <br>Per a Instagram, fes una captura de pantalla del certificat de dalt!
        </p>
        
        <div style="text-align:center; margin-top:35px; padding:20px; background: var(--background-fill-secondary); border-radius:12px; border:2px solid var(--color-accent);">
            <p style="font-size:1.15rem; font-weight:800; color:var(--color-accent); margin-bottom:5px;">
                🚀 CONTINUA CAP A LA COMPETICIÓ FINAL
            </p>
            <p style="font-size:1.05rem; margin:0; color: var(--body-text-color);">
               Fes clic a <strong>Següent</strong> per finalitzar la teva certificació.
            </p>
        </div> 
    </div>
    """

    return gr.update(value=cert_html, visible=True), gr.update(value=share_html, visible=True)
    
# --- 9. APP FACTORY ---
# --- 9. APP FACTORY ---
def create_sustainability_upgrade_ca_app(theme_primary_hue: str = "indigo"):
    with gr.Blocks(theme=gr.themes.Soft(primary_hue=theme_primary_hue), css=css) as demo:
        # States
        username_state = gr.State(value=None)
        token_state = gr.State(value=None)
        team_state = gr.State(value=None)

        # --- 1. LOADING STATE ---
        with gr.Column(visible=True, elem_id="app-loader") as loader_col:
            gr.HTML("<div style='text-align:center; padding:100px;'><h2>🏆 Verificant credencials...</h2></div>")

        # --- 2. AUTH FAILED STATE ---
        with gr.Column(visible=False, elem_id="auth-fail") as auth_fail_col:
            gr.HTML(
                """
                <div style='text-align:center; padding:100px; color: #EF4444;'>
                    <h2>🚫 Autenticació fallida</h2>
                    <p style='font-size: 1.2em;'>No hem pogut verificar la teva sessió.</p>
                    <p>Si us plau, torna a la pàgina d'inici de sessió i torna-ho a provar.</p>
                    <br/>
                    <a href='/login' style='background-color:#EF4444; color:white; padding:10px 20px; text-decoration:none; border-radius:5px;'>Anar a l'Inici de Sessió</a>
                </div>
                """
            )

        # --- 3. MAIN APP STATE ---
        with gr.Column(visible=False) as main_app_col:

            # Module containers
            module_ui_elements = {}
            
            # Variables to hold module 0 outputs (needed for .load() later)
            # We initialize them here so they exist in scope even if loop fails (safety)
            dash_output = None
            lb_output = None

            for i, mod in enumerate(MODULES):
                with gr.Column(visible=(i==0), elem_id=f"mod-{i}") as mod_col:
                    gr.HTML(mod["html"])

                    # --- MODULE 0 PART 1: SCORE DASHBOARD ---
                    # We render the top dashboard BEFORE the buttons
                    if i == 0:
                        dash_output = gr.HTML()

                    # --- MODULE 2 SPECIFIC: INPUTS ---
                    # Inputs for the certificate generator usually go above the buttons
                    if i == 2:
                        name_input = gr.Textbox(label="Nom complet per al certificat", placeholder="p. ex. Maria Garcia")
                        gen_btn = gr.Button("🎓 Genera el teu certificat", variant="primary")
                        cert_display = gr.HTML(label="Certificat oficial", visible=False)
                        share_row = gr.HTML(visible=False)

                        gen_btn.click(
                            create_cert_handler,
                            inputs=[name_input, username_state, token_state, team_state],
                            outputs=[cert_display, share_row]
                        )

                    # --- NAVIGATION BUTTONS ---
                    # These are now placed in the middle for Module 0, or bottom for others
                    with gr.Row():
                        btn_prev = gr.Button("⬅️ Anterior", visible=(i > 0))
                        next_txt = "Següent ▶️" if i < len(MODULES) - 1 else "CONTINUAR A L'ACTIVITAT 9 →"
                        btn_next = gr.Button(next_txt, visible=True, variant="primary" if i == len(MODULES) - 1 else "secondary")

                    # --- MODULE 0 PART 2: LEADERBOARD ---
                    # We render the leaderboard AFTER the buttons
                    if i == 0:
                        lb_output = gr.HTML()

                    module_ui_elements[i] = (mod_col, btn_prev, btn_next)

            # --- NAVIGATION LOGIC ---
            for i in range(len(MODULES)):
                curr_col, prev_btn, next_btn = module_ui_elements[i]

                if i > 0:
                    prev_col = module_ui_elements[i-1][0]
                    def nav_back():
                        return gr.update(visible=False), gr.update(visible=True)
                    prev_btn.click(nav_back, None, [curr_col, prev_col])

                if i < len(MODULES) - 1:
                    next_col = module_ui_elements[i+1][0]
                    def nav_fwd():
                        return gr.update(visible=False), gr.update(visible=True)
                    next_btn.click(nav_fwd, None, [curr_col, next_col])

            # Navigate to next activity from last module
            last_idx = len(MODULES) - 1
            _, _, last_next = module_ui_elements[last_idx]
            last_next.click(
                fn=None,
                js="() => { try { window.parent.postMessage('navigate-to-activity-9', '*'); } catch(e) {} }"
            )

        # --- LOAD HANDLER ---
        def handle_load(req: gr.Request):
            success, user, token = _try_session_based_auth(req)
            
            # --- FAILURE LOGIC ---
            if not success:
                return (
                    None, None, None,           # States
                    gr.update(visible=False),   # Loader -> Hide
                    gr.update(visible=True),    # Auth Fail -> SHOW
                    gr.update(visible=False),   # Main App -> Hide
                    "", ""                      # Dashboard/Leaderboard HTML
                )

            # Fetch team/score data using the complex fetcher
            try:
                os.environ["MORAL_COMPASS_API_BASE_URL"] = DEFAULT_API_URL
                client = MoralcompassApiClient(api_base_url=DEFAULT_API_URL, auth_token=token)

                # Simple fetch to get team name
                _, simple_team = fetch_user_history(user, token)

                # Complex fetch for leaderboard logic
                data = get_leaderboard_data(client, user, simple_team)

                # Render App 2 Components for Module 0
                dashboard_html = render_top_dashboard(data)
                leaderboard_html = render_leaderboard_card(data, user, simple_team)
            except Exception as e:
                # Optional: Fallback if API fails even if Auth worked
                print(f"API Error: {e}")
                dashboard_html = "<div>Error en carregar les dades</div>"
                leaderboard_html = ""

            # --- SUCCESS LOGIC ---
            return (
                user, token, simple_team,  # States
                gr.update(visible=False),  # Loader -> Hide
                gr.update(visible=False),  # Auth Fail -> Hide
                gr.update(visible=True),   # Main App -> SHOW
                dashboard_html, leaderboard_html
            )

        demo.load(
            handle_load,
            None,
            [
                username_state,
                token_state,
                team_state,
                loader_col,
                auth_fail_col,
                main_app_col,
                dash_output,
                lb_output
            ],
            js="() => { try { window.parent.postMessage('app-ready', '*'); } catch(e) {} }",
        )

    return demo

def launch_sustainability_upgrade_ca_app(share=False,
                           server_port=8080,
                           **kwargs):
    app = create_sustainability_upgrade_ca_app()
    app.launch(share=share,
               server_port=server_port,
               **kwargs)

if __name__ == "__main__":
    launch_sustainability_upgrade_ca_app(share=False, debug=True, height=1000)
