"""
FROST Air Quality Widget - Mappa Sensori
Visualizzazione geografica di tutti i sensori installati
"""

import streamlit as st
import folium
from streamlit_folium import st_folium
import requests
from pathlib import Path
import pandas as pd
from datetime import datetime
import base64
import math
from widget_app_v5 import calculate_air_quality_index
from folium.plugins import MarkerCluster


from collections import defaultdict


# Import moduli comuni
from frost_client import FROSTClient, parse_time
from frost_utils import load_standard, build_alias_index, detect_measure, get_datastream_config
# IMMAGINI


IMAGES = {
    'esclamativo': 'assets/esclamativo.png',
    'error_s': 'assets/error_s.png',
    'air_quality_nullo': 'assets/nullo.png'
}


def get_image_base64(image_path):
    """Converte immagine in base64 per embedding HTML"""
    try:
        with open(image_path, "rb") as f:
            data = f.read()
            return base64.b64encode(data).decode()
    except:
        return None
    
# CONFIGURAZIONI
CLASSI_NAMES = {
    "THI.FE.019":"aula 13", "THI.FE.020": "aula 11", "THI.FE.021": "aula 10",
    "THI.FE.022": "aula 5", "THI.FE.023": "aula 2", "THI.FE.024":"lab",
    "THI.FE.014":"aula 5", "THI.FE.015":"aula T2", "THI.FE.016":"aula 2",
    "THI.FE.017":"aula 18", "THI.FE.018":"aula 21", "THI.FE.010":"aula 1 CAT",
    "THI.FE.011":"ricreazione", "THI.FE.012":"aula 23", "THI.FE.013":"lab. inf. 3",
    "THI.FE.001":"casa Verri", "THI.FE.002":"Ufficio M.", "THI.FE.003":"Ufficio I.",
    "THI.FE.004":"Ufficio R.", "THI.FE.005":"Ufficio C.", "THI.FE.006":"Ufficio M.",
    "THI.FE.007":"primo piano", "THI.FE.008":"Ufficio G.", "THI.FE.030":"Public Relations",
    "THI.FE.031":"waiting zone", "THI.FE.032":"Ufficio T.", "THI.FE.033":"Ufficio B.",
    "THI.FE.034":"Ufficio C.", "THI.FE.035":"Ufficio P.", "THI.FE.025":"Fitness Gym 1",
    "THI.FE.026":"Cardio Gym", "THI.FE.027":"Fitness Gym 2", "THI.FE.028":"Reception",
    "THI.FE.029":"Spinning Gym", "THI.FE.036":"Reception", "THI.FE.009":"Ristorante Iaia",
}

ISTITUTI = {
    "Istituto Copernico": ["THI.FE.019","THI.FE.020","THI.FE.021","THI.FE.023", "THI.FE.022","THI.FE.024"],
    "Istituto Carducci": ["THI.FE.014","THI.FE.015","THI.FE.016","THI.FE.017","THI.FE.018"],
    "Istituto Aleotti": ["THI.FE.010", "THI.FE.011", "THI.FE.012", "THI.FE.013"],
    "Casa Verri": ["THI.FE.001"],
    "Agenzia Mobilità Impianti Ferrara": ["THI.FE.002","THI.FE.003","THI.FE.004"],
    "Comune Ferrara via Maverna": ["THI.FE.005","THI.FE.006","THI.FE.007","THI.FE.008"],
    "Ristorante Iaia": ["THI.FE.009"],
    "Centro Universitario Sportivo di Ferrara": ["THI.FE.025","THI.FE.026","THI.FE.027","THI.FE.028","THI.FE.029"],
    "Comune Ferrara via Marconi": ["THI.FE.030","THI.FE.031","THI.FE.032","THI.FE.033","THI.FE.034","THI.FE.035"],
    "Deda Next": ["THI.FE.036"]
}

AIR_QUALITY_LABELS = ["Buona", "Accettabile", "Mediocre", "Scadente", "Inaccettabile", "Pessima"]
AIR_QUALITY_COLORS = ["#00f9e5", "#00d5a7", "#ffb700", "#ff004f", "#9e0035", "#890082"]

# PAGE CONFIG
st.set_page_config(
    page_title="Mappa Sensori - Monitoraggio Qualità Aria",
    page_icon='assets/ediaqi_logo3.png',
    layout="wide",
    initial_sidebar_state="collapsed"
)

# CSS
st.markdown("""
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
        * { font-family: 'Inter', sans-serif; }
        .stApp { background: #f1f1f1; }
        
        .map-header {
            background: white;
            padding: 20px 30px;
            border-radius: 12px;
            margin-bottom: 20px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.08);
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .map-title {
            font-size: 28px;
            font-weight: 700;
            color: #006278;
        }
        
        .sensor-popup {
            font-family: 'Inter', sans-serif;
        }
        
        .popup-title {
            font-size: 16px;
            font-weight: 700;
            color: #006278;
            margin-bottom: 8px;
        }
        
        .popup-subtitle {
            font-size: 13px;
            color: #666;
            margin-bottom: 12px;
        }
        
        .details-box {
            background: white;
            padding: 25px;
            border-radius: 12px;
            box-shadow: 0 2px 12px rgba(0,0,0,0.08);
            margin-top: 20px;
        }
        
        .detail-section {
            margin-bottom: 20px;
        }
        
        .detail-title {
            font-size: 18px;
            font-weight: 700;
            color: #006278;
            margin-bottom: 10px;
            border-bottom: 2px solid #00d5a7;
            padding-bottom: 5px;
        }
        
        .detail-item {
            display: grid;
            grid-template-columns: 200px 1fr;
            gap: 15px;
            padding: 8px 0;
            border-bottom: 1px solid #f0f0f0;
        }
        
        .detail-label {
            font-weight: 600;
            color: #444;
        }
        
        .detail-value {
            color: #666;
        }
        
        .block-container {
            max-width: 1400px !important;
            padding-top: 2rem;
        }
            


        @keyframes slideDown {
            from { transform: translateY(0); opacity: 1; }
            to { transform: translateY(100%); opacity: 0; }
        }
        
        .details-closing {
            animation: slideDown 0.3s ease-out forwards !important;
        }
    </style>
""", unsafe_allow_html=True)

# INIZIALIZZA SESSION STATE
if 'authenticated' not in st.session_state:
    st.session_state.authenticated = False
if 'client' not in st.session_state:
    st.session_state.client = None
if 'selected_sensor' not in st.session_state:
    st.session_state.selected_sensor = None
if 'show_details' not in st.session_state:
    st.session_state.show_details = False

if 'from_advanced_view' not in st.session_state:
    st.session_state.from_advanced_view = False
if 'coming_from_map' not in st.session_state:
    st.session_state.coming_from_map = False

# FUNZIONI
def load_config():
    """Carica configurazione"""
    return {
        'endpoint': 'https://frost.labservice.it/FROST-Server/v1.1',
        'standard_url': 'https://drive.google.com/uc?export=download&id=1qDfuIjL3NC25sZ3HDgpM3SewmrZTB-7Q',
        'timezone': 'Europe/Rome'
    }

def get_thing_from_location_id(location_id):
    """Estrae Thing ID da Location ID"""
    return location_id.replace('LOC.', 'THI.')

def get_istituto_for_thing(thing_id):
    """Trova l'istituto di appartenenza di un Thing"""
    for istituto, things in ISTITUTI.items():
        if thing_id in things:
            return istituto
    return "N/A"

def fetch_locations(client):
    """Scarica tutte le locations dal server FROST"""
    try:
        response = requests.get(
            f"{client.base_url}/Locations",
            auth=client.auth,
            params={"$top": 1000}
        )
        response.raise_for_status()
        data = response.json()
        return data.get('value', [])
    except Exception as e:
        st.error(f"Errore caricamento locations: {e}")
        return []

def fetch_feature_of_interest(client, thing_id):
    """Scarica Feature of Interest per un Thing"""
    try:
        thing = client.get_thing(thing_id)
        if not thing:
            return None
        
        datastreams = client.get_datastreams(thing['@iot.id'])
        if not datastreams:
            return None
        
        ds_id = datastreams[0].get('@iot.id')
        response = requests.get(
            f"{client.base_url}/Datastreams({ds_id})/Observations",
            auth=client.auth,
            params={"$top": 1, "$expand": "FeatureOfInterest"}
        )
        response.raise_for_status()
        data = response.json()
        
        observations = data.get('value', [])
        if observations and 'FeatureOfInterest' in observations[0]:
            return observations[0]['FeatureOfInterest']
        
        return None
    except Exception as e:
        st.warning(f"Errore caricamento Feature of Interest: {e}")
        return None

def create_categorical_heatmap(client, thing_id, standard, timezone='Europe/Rome'):
    """Crea heatmap categorica per un sensore"""
    import plotly.graph_objects as go
    import pytz
    
    try:
        thing = client.get_thing(thing_id)
        if not thing:
            return None
        
        datastreams = client.get_datastreams_with_latest(thing['@iot.id'])
        if not datastreams:
            return None
        
        first_ds = client.get_datastreams(thing['@iot.id'])
        if not first_ds:
            return None
        
        first_obs = client.get_latest_observation(first_ds[0].get('@iot.id'))
        if not first_obs:
            return None
        
        ref_time = parse_time(first_obs.get('phenomenonTime'))
        if pd.isna(ref_time):
            return None
        
        ref_time_dt = ref_time.to_pydatetime().replace(tzinfo=None)
        
        datastream_labels = standard.get("datastreamLabels", [])
        pollutants_to_check = ['PM2.5', 'PM10', 'NO2', 'CO2', 'CO', 'O3', 'TVOCs']
        alias_idx = build_alias_index(standard)
        
        pollutant_indices = {}
        
        for ds in datastreams:
            ds_id = ds.get('@iot.id')
            name = ds.get('name') or ""
            
            detected_name = detect_measure(name, alias_idx, datastream_labels)
            if not detected_name:
                op_name = (ds.get("ObservedProperty") or {}).get("name") or ""
                detected_name = detect_measure(op_name, alias_idx, datastream_labels)
            
            if not detected_name or detected_name not in pollutants_to_check:
                continue
            
            ds_config = get_datastream_config(detected_name, datastream_labels)
            if not ds_config:
                continue
            
            thresholds = ds_config.get("categoryThresholds", [])
            if len(thresholds) != 5:
                continue
            
            greater_worse = ds_config.get("greaterIsWorse", True)
            
            obs = client.get_observations_timerange(
                ds_id, 
                hours_back=24,
                limit=500,
                reference_time=ref_time_dt,
                select_clause='phenomenonTime,result'
            )
            
            if not obs:
                continue
            
            time_value_pairs = []
            
            for o in obs:
                t = parse_time(o.get('phenomenonTime'))
                val = o.get('result')
                
                if pd.isna(t) or val is None:
                    continue
                
                try:
                    val = float(val)
                except:
                    continue
                
                if val < 0:
                    continue
                
                if greater_worse:
                    if val <= thresholds[0]:
                        normalized = (val / thresholds[0]) * 16
                    elif val <= thresholds[1]:
                        normalized = 16 + ((val - thresholds[0]) / (thresholds[1] - thresholds[0])) * 16
                    elif val <= thresholds[2]:
                        normalized = 32 + ((val - thresholds[1]) / (thresholds[2] - thresholds[1])) * 16
                    elif val <= thresholds[3]:
                        normalized = 48 + ((val - thresholds[2]) / (thresholds[3] - thresholds[2])) * 16
                    elif val <= thresholds[4]:
                        normalized = 64 + ((val - thresholds[3]) / (thresholds[4] - thresholds[3])) * 16
                    else:
                        log_component = 8 * math.log2(val / thresholds[4])
                        normalized = min(80 + log_component, 100)
                else:
                    if val <= 0:
                        normalized = 100
                    elif val >= thresholds[0]:
                        normalized = (thresholds[0] / val) * 16
                        normalized = min(normalized, 16)
                    elif val >= thresholds[1]:
                        normalized = 16 + ((thresholds[0] - val) / (thresholds[0] - thresholds[1])) * 16
                    elif val >= thresholds[2]:
                        normalized = 32 + ((thresholds[1] - val) / (thresholds[1] - thresholds[2])) * 16
                    elif val >= thresholds[3]:
                        normalized = 48 + ((thresholds[2] - val) / (thresholds[2] - thresholds[3])) * 16
                    elif val >= thresholds[4]:
                        normalized = 64 + ((thresholds[3] - val) / (thresholds[3] - thresholds[4])) * 16
                    else:
                        if val > 0:
                            ratio = thresholds[4] / val
                            log_component = 8 * math.log2(1 / ratio)
                            normalized = min(80 + log_component, 100)
                        else:
                            normalized = 100
                
                if normalized is not None:
                    time_value_pairs.append((t, normalized))
            
            if time_value_pairs:
                pollutant_indices[detected_name] = time_value_pairs
        
        if not pollutant_indices:
            return None
        
        pollutant_data = {}
        all_times = set()
        
        for pollutant, data in pollutant_indices.items():
            times = [d[0] for d in data]
            values = [d[1] for d in data]
            
            if not times:
                continue
            
            categories = []
            for val in values:
                if val < 16:
                    categories.append(0)
                elif val < 32:
                    categories.append(1)
                elif val < 48:
                    categories.append(2)
                elif val < 64:
                    categories.append(3)
                elif val < 80:
                    categories.append(4)
                else:
                    categories.append(5)
            
            pollutant_data[pollutant] = {'times': times, 'categories': categories}
            all_times.update(times)
        
        if not all_times:
            return None
        
        sorted_times = sorted(list(all_times))
        
        ediaqi_categories = []
        for t in sorted_times:
            max_cat = 0
            for pollutant, data in pollutant_data.items():
                try:
                    idx = data['times'].index(t)
                    max_cat = max(max_cat, data['categories'][idx])
                except ValueError:
                    continue
            ediaqi_categories.append(max_cat)
        
        local_tz = pytz.timezone(timezone)
        times_converted = pd.to_datetime(sorted_times, utc=True).tz_convert(local_tz)
        
        pollutants_order = ['<b>IAQ</b>'] + list(pollutant_data.keys())
        z_data = [ediaqi_categories]
        
        for pollutant in pollutant_data.keys():
            row = []
            for t in sorted_times:
                try:
                    idx = pollutant_data[pollutant]['times'].index(t)
                    row.append(pollutant_data[pollutant]['categories'][idx])
                except ValueError:
                    row.append(None)
            z_data.append(row)
        
        fig = go.Figure(data=go.Heatmap(
            z=z_data,
            x=times_converted,
            y=pollutants_order,
            colorscale=[
                [0, AIR_QUALITY_COLORS[0]],
                [0.2, AIR_QUALITY_COLORS[1]],
                [0.4, AIR_QUALITY_COLORS[2]],
                [0.6, AIR_QUALITY_COLORS[3]],
                [0.8, AIR_QUALITY_COLORS[4]],
                [1.0, AIR_QUALITY_COLORS[5]]
            ],
            showscale=False,
            hovertemplate='%{y}<br>%{x}<br>Categoria: %{customdata}<extra></extra>',
            customdata=[[AIR_QUALITY_LABELS[val] if val is not None else 'N/A' for val in row] for row in z_data],
            zmin=0,
            zmax=5,
            ygap=16
        ))
        
        fig.update_layout(
            height=350,
            annotations=[
                dict(
                    x=0.05 + (i * 0.15),
                    y=-0.28,
                    xref='paper',
                    yref='paper',
                    text=f'<span style="color:{AIR_QUALITY_COLORS[i]}; font-size:20px">■</span> {AIR_QUALITY_LABELS[i]}',
                    showarrow=False,
                    font=dict(size=14),
                    xanchor='left'
                ) for i in range(6)
            ],
            margin=dict(l=50, r=40, t=20, b=80),
            xaxis=dict(showgrid=False, title=None),
            yaxis=dict(showgrid=False, title=None, tickmode='linear', dtick=1, autorange='reversed'),
            plot_bgcolor='white',
            paper_bgcolor='white',
            font=dict(family='Inter', size=12)
        )
        
        return fig
        
    except Exception as e:
        st.error(f"Errore creazione heatmap: {e}")
        return None


def render_location_details(location):
    """Renderizza i dettagli della location in modo gerarchico completo"""
    
    loc_props = location.get('properties', {})
    
    st.markdown("""
        <style>
        .detail-section {
            margin-bottom: 24px;
        }
        
        .detail-title {
            font-size: 16px;
            font-weight: 700;
            color: #006278;
            margin-bottom: 12px;
            border-bottom: 2px solid #00d5a7;
            padding-bottom: 8px;
        }
        
        .detail-item {
            padding: 12px;
            background: #f8f9fa;
            border-radius: 8px;
            border-left: 3px solid #00d5a7;
            margin-bottom: 8px;
        }
        
        .detail-label {
            font-size: 12px;
            font-weight: 600;
            color: #666;
            text-transform: uppercase;
            margin-bottom: 4px;
            letter-spacing: 0.5px;
        }
        
        .detail-value {
            font-size: 14px;
            color: #333;
            font-weight: 500;
        }
        </style>
    """, unsafe_allow_html=True)
    
    # Header
    st.markdown(f"""
        <div class="detail-section">
            <div style="font-size:22px; font-weight:700; color:#006278; margin-bottom:4px;">
                {location.get('name', 'N/A')}
            </div>
            <div style="font-size:13px; color:#999;">
                {location.get('description', 'Nessuna descrizione')}
            </div>
        </div>
    """, unsafe_allow_html=True)
    
    # === INFORMAZIONI GENERALI ===
    st.markdown('<div class="detail-title">📍 Informazioni Generali</div>', unsafe_allow_html=True)
    
    col1, col2 = st.columns(2)
    with col1:
        st.markdown(f"""
            <div class="detail-item">
                <div class="detail-label">ID Identificativo</div>
                <div class="detail-value">{loc_props.get('identifier', 'N/A')}</div>
            </div>
        """, unsafe_allow_html=True)
    with col2:
        st.markdown(f"""
            <div class="detail-item">
                <div class="detail-label">ID Locale</div>
                <div class="detail-value">{loc_props.get('localIdentifier', 'N/A')}</div>
            </div>
        """, unsafe_allow_html=True)
    
    col1, col2 = st.columns(2)
    with col1:
        st.markdown(f"""
            <div class="detail-item">
                <div class="detail-label">Indirizzo</div>
                <div class="detail-value">{loc_props.get('address', 'N/A')}</div>
            </div>
        """, unsafe_allow_html=True)
    with col2:
        st.markdown(f"""
            <div class="detail-item">
                <div class="detail-label">Paese</div>
                <div class="detail-value">{loc_props.get('country', 'N/A')}</div>
            </div>
        """, unsafe_allow_html=True)
    
    # === EDIFICIO ===
    st.markdown('<div class="detail-title" style="margin-top:20px;">🏢 Edificio</div>', unsafe_allow_html=True)
    
    col1, col2 = st.columns(2)
    with col1:
        st.markdown(f"""
            <div class="detail-item">
                <div class="detail-label">Uso dell'Edificio</div>
                <div class="detail-value">{loc_props.get('useOfTheBuilding', 'N/A')}</div>
            </div>
        """, unsafe_allow_html=True)
    with col2:
        st.markdown(f"""
            <div class="detail-item">
                <div class="detail-label">Dettagli Utilizzo</div>
                <div class="detail-value">{loc_props.get('detailsAboutTheUse', 'N/A')}</div>
            </div>
        """, unsafe_allow_html=True)
    
    col1, col2 = st.columns(2)
    with col1:
        st.markdown(f"""
            <div class="detail-item">
                <div class="detail-label">Proprietario</div>
                <div class="detail-value">{loc_props.get('owner', 'N/A')}</div>
            </div>
        """, unsafe_allow_html=True)
    with col2:
        is_outdoor = 'Sì (Esterno)' if loc_props.get('isOutdoor') else 'No (Interno)'
        st.markdown(f"""
            <div class="detail-item">
                <div class="detail-label">Posizione</div>
                <div class="detail-value">{is_outdoor}</div>
            </div>
        """, unsafe_allow_html=True)
    
    # OSM ID
    if loc_props.get('idOfTheBuildingInOpenStreetMap'):
        st.markdown(f"""
            <div class="detail-item">
                <div class="detail-label">ID OpenStreetMap</div>
                <div class="detail-value">{loc_props.get('idOfTheBuildingInOpenStreetMap')}</div>
            </div>
        """, unsafe_allow_html=True)
    
    # === STANZA / AMBIENTE ===
    if 'room' in loc_props:
        room = loc_props['room']
        
        st.markdown('<div class="detail-title" style="margin-top:20px;">🚪 Stanza / Ambiente</div>', unsafe_allow_html=True)
        
        col1, col2 = st.columns(2)
        with col1:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Piano</div>
                    <div class="detail-value">{room.get('levelFloor', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        with col2:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Elevazione (m)</div>
                    <div class="detail-value">{room.get('elevationOfTheThing', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        
        col1, col2 = st.columns(2)
        with col1:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Distanza dalle Pareti (m)</div>
                    <div class="detail-value">{room.get('horizontalDistanceFromWalls', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        with col2:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Distanza dal Pavimento (m)</div>
                    <div class="detail-value">{room.get('verticalDistanceFromPavementOrGround', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        
        col1, col2 = st.columns(2)
        with col1:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Distanza dal Soffitto (m)</div>
                    <div class="detail-value">{room.get('verticalDistanceFromCeilingOfTheRoom', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)


def render_foi_details(foi):
    """Renderizza i dettagli del Feature of Interest in modo gerarchico completo"""
    
    foi_props = foi.get('properties', {})
    
    st.markdown("""
        <style>
        .detail-section {
            margin-bottom: 24px;
        }
        
        .detail-title {
            font-size: 16px;
            font-weight: 700;
            color: #006278;
            margin-bottom: 12px;
            border-bottom: 2px solid #00d5a7;
            padding-bottom: 8px;
        }
        
        .detail-item {
            padding: 12px;
            background: #f8f9fa;
            border-radius: 8px;
            border-left: 3px solid #00d5a7;
            margin-bottom: 8px;
        }
        
        .detail-label {
            font-size: 12px;
            font-weight: 600;
            color: #666;
            text-transform: uppercase;
            margin-bottom: 4px;
            letter-spacing: 0.5px;
        }
        
        .detail-value {
            font-size: 14px;
            color: #333;
            font-weight: 500;
        }
        </style>
    """, unsafe_allow_html=True)
    
    # Header
    st.markdown(f"""
        <div class="detail-section">
            <div style="font-size:22px; font-weight:700; color:#006278; margin-bottom:4px;">
                {"Info Stanza"}
            </div>
        </div>
    """, unsafe_allow_html=True)
    
    # === INFORMAZIONI GENERALI ===
    st.markdown('<div class="detail-title">📋 Informazioni Generali</div>', unsafe_allow_html=True)
    
    col1, col2 = st.columns(2)
    with col1:
        st.markdown(f"""
            <div class="detail-item">
                <div class="detail-label">ID Identificativo</div>
                <div class="detail-value">{foi_props.get('identifier', 'N/A')}</div>
            </div>
        """, unsafe_allow_html=True)
    with col2:
        st.markdown(f"""
            <div class="detail-item">
                <div class="detail-label">ID Locale</div>
                <div class="detail-value">{foi_props.get('localIdentifier', 'N/A')}</div>
            </div>
        """, unsafe_allow_html=True)
    
    # === STANZA / AMBIENTE ===
    if 'room' in foi_props:
        room = foi_props['room']
        
        st.markdown('<div class="detail-title" style="margin-top:20px;">🚪 Stanza / Ambiente</div>', unsafe_allow_html=True)
        
        col1, col2 = st.columns(2)
        with col1:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Uso della Stanza</div>
                    <div class="detail-value">{room.get('useOfTheSingleRoom', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        with col2:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Dettagli Utilizzo</div>
                    <div class="detail-value">{room.get('useDetails', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        
        col1, col2 = st.columns(2)
        with col1:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Area (m²)</div>
                    <div class="detail-value">{room.get('floorArea', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        with col2:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Area Vetrata (m²)</div>
                    <div class="detail-value">{room.get('glazedArea', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        
        col1, col2 = st.columns(2)
        with col1:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Piano</div>
                    <div class="detail-value">{room.get('levelFloor', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        with col2:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Altezza Interna (m)</div>
                    <div class="detail-value">{room.get('indoorHeightOfTheRoom', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        
        # Ventilazione
        st.markdown(f"""
            <div class="detail-item">
                <div class="detail-label">Ventilazione</div>
                <div class="detail-value">{room.get('ventilation', 'N/A')}</div>
            </div>
        """, unsafe_allow_html=True)
    
    # === OCCUPANTI ===
    if 'occupants' in foi_props:
        occupants = foi_props['occupants']
        if isinstance(occupants, list):
            occupants = occupants[0] if occupants else {}
        
        st.markdown('<div class="detail-title" style="margin-top:20px;">👥 Occupanti</div>', unsafe_allow_html=True)
        
        col1, col2 = st.columns(2)
        with col1:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Numero Occupanti</div>
                    <div class="detail-value">{occupants.get('numberOfOccupants', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        with col2:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Genere</div>
                    <div class="detail-value">{occupants.get('genderOfOccupants', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        
        col1, col2 = st.columns(2)
        with col1:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Tipo Principale</div>
                    <div class="detail-value">{occupants.get('mainTypeOfOccupants', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        with col2:
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">Fascia di Età</div>
                    <div class="detail-value">{occupants.get('averageAgeOfOccupants', 'N/A')}</div>
                </div>
            """, unsafe_allow_html=True)
        
        # Orari di Occupazione
        st.markdown('<div class="detail-title" style="margin-top:20px;">⏰ Orari di Occupazione</div>', unsafe_allow_html=True)
        
        occupancy_schedule = {
            'occupancyHoursMon': 'Lunedì',
            'occupancyHoursTue': 'Martedì',
            'occupancyHoursWed': 'Mercoledì',
            'occupancyHoursThu': 'Giovedì',
            'occupancyHoursFri': 'Venerdì',
            'occupancyHoursSat': 'Sabato',
            'occupancyHoursSun': 'Domenica',
        }
        
        for key, label in occupancy_schedule.items():
            value = occupants.get(key, 'N/A')
            st.markdown(f"""
                <div class="detail-item">
                    <div class="detail-label">{label}</div>
                    <div class="detail-value">{value}</div>
                </div>
            """, unsafe_allow_html=True)




@st.dialog("🏠 Dettagli Stanza", width="large")
def show_combined_details_dialog(location, client, thing_id):
    """Dialog combinato per Location + Feature of Interest"""
    
    # === PARTE LOCATION ===
    st.markdown('<div style="margin-bottom:30px;">', unsafe_allow_html=True)
    render_location_details(location)
    st.markdown('</div>', unsafe_allow_html=True)
    
    # === PARTE FEATURE OF INTEREST ===
    st.markdown('<hr style="border:1px solid #e0e0e0; margin:30px 0;">', unsafe_allow_html=True)
    
    with st.spinner("Caricamento informazioni aggiuntive..."):
        foi = fetch_feature_of_interest(client, thing_id)
    
    if foi:
        render_foi_details(foi)
    else:
        st.info("Informazioni aggiuntive non disponibili per questo sensore")

    

# MAIN APP
CONFIG = load_config()

# Verifica autenticazione
if not st.session_state.authenticated or st.session_state.client is None:
    st.error("Devi effettuare il login per accedere alla mappa.")
    if st.button("← Torna al Login"):
        st.switch_page("pages/main.py")
    st.stop()

client = st.session_state.client

# Carica standard
if 'standard' not in st.session_state or st.session_state.standard is None:
    from frost_utils import load_standard
    with st.spinner("Caricamento standard..."):
        st.session_state.standard = load_standard(CONFIG['standard_url'])

standard = st.session_state.standard

# RESETTA DETTAGLI ALL'APERTURA DELLA MAPPA (SEMPRE)
if 'map_page_just_opened' not in st.session_state or not st.session_state.map_page_just_opened:
    st.session_state.show_details = False
    st.session_state.selected_sensor = None
    st.session_state.map_page_just_opened = True
elif st.session_state.get('show_details', False):
    # Se arriviamo qui con show_details=True, significa che torniamo dalla dashboard
    # Mantieni i dettagli aperti SOLO se c'è un sensore selezionato valido
    if st.session_state.get('selected_sensor') is None:
        st.session_state.show_details = False

# GESTIONE CHIUSURA DETTAGLI - DEVE ESSERE QUI ALL'INIZIO
if 'close_details_clicked' in st.session_state and st.session_state.close_details_clicked:
    st.session_state.show_details = False
    st.session_state.selected_sensor = None
    st.session_state.close_details_clicked = False
    st.rerun()

st.markdown('</div>', unsafe_allow_html=True)
# CARICA LOCATIONS

with st.spinner("Caricamento sensori..."):
    locations = fetch_locations(client)

if not locations:
    st.error("Nessun sensore trovato")
    st.stop()

# CALCOLA AQI PER TUTTI I SENSORI
if 'sensor_aqi_map' not in st.session_state:
    with st.spinner("Calcolo qualità aria sensori..."):
        sensor_aqi_map = {}
        sensor_colors = {}
        now = datetime.now()
        
        for loc in locations:
            location_id = loc.get('@iot.id', '')
            thing_id = get_thing_from_location_id(location_id)
            
            try:
                # Ottieni reference time
                thing = client.get_thing(thing_id)
                if not thing:
                    sensor_colors[thing_id] = '#9ca3af'  # Grigio
                    continue
                
                first_ds = client.get_datastreams(thing['@iot.id'])
                if not first_ds:
                    sensor_colors[thing_id] = '#9ca3af'
                    continue
                    
                first_obs = client.get_latest_observation(first_ds[0].get('@iot.id'))
                if not first_obs:
                    sensor_colors[thing_id] = '#9ca3af'
                    continue
                
                ref_time = parse_time(first_obs.get('phenomenonTime'))
                if pd.isna(ref_time):
                    sensor_colors[thing_id] = '#9ca3af'
                    continue
                    
                ref_time_dt = ref_time.to_pydatetime().replace(tzinfo=None)
                
                # Verifica se dati recenti (ultime 6 ore)
                time_diff = (now - ref_time_dt).total_seconds() / 3600
                
                if time_diff > 6:
                    sensor_colors[thing_id] = '#9ca3af'  # Grigio per offline
                    sensor_aqi_map[thing_id] = None
                    continue
                
                # Calcola AQI usando la stessa funzione di widget_app
                datastreams = client.get_datastreams_with_latest(thing['@iot.id'])
                if not datastreams:
                    sensor_colors[thing_id] = '#9ca3af'
                    continue
                
                # Costruisci latest_data
                from frost_utils import build_alias_index, detect_measure
                alias_idx = build_alias_index(standard)
                datastream_labels = standard.get("datastreamLabels", [])
                
                latest_data = {}
                for ds in datastreams:
                    ds_id = ds.get('@iot.id')
                    name = ds.get('name') or ""
                    
                    detected_name = detect_measure(name, alias_idx, datastream_labels)
                    if not detected_name:
                        op_name = (ds.get("ObservedProperty") or {}).get("name") or ""
                        detected_name = detect_measure(op_name, alias_idx, datastream_labels)
                    
                    if detected_name:
                        obs = ds.get('Observations', [])
                        if obs:
                            latest_data[detected_name] = obs[0].get('result')
                
                # Calcola AQI
                from widget_app_v5 import calculate_air_quality_index
                _, air_category, has_null, _ = calculate_air_quality_index(
                    datastreams, 
                    client, 
                    standard, 
                    ref_time_dt,
                    latest_data=latest_data
                )
                
                sensor_aqi_map[thing_id] = air_category
                
                # Assegna colore in base alla categoria
                if has_null or air_category is None:
                    sensor_colors[thing_id] = '#9ca3af'  # Grigio
                else:
                    sensor_colors[thing_id] = AIR_QUALITY_COLORS[air_category]
                    
            except Exception as e:
                sensor_colors[thing_id] = '#9ca3af'
                sensor_aqi_map[thing_id] = None
        st.session_state.sensor_aqi_map = sensor_aqi_map
        st.session_state.sensor_colors = sensor_colors
else:
    sensor_aqi_map = st.session_state.sensor_aqi_map
    sensor_colors = st.session_state.sensor_colors

# CREA MAPPA
m = folium.Map(
    location=[44.8378, 11.6196],
    zoom_start=13,
    tiles='CartoDB positron'    # per stile chiaro ---> 'CartoDB positron'
)

cluster = MarkerCluster(
    disableClusteringAtZoom=17,
    maxClusterRadius=50
).add_to(m)




# 1. Raggruppa le locations per coordinate
coord_groups = defaultdict(list)
offset_coords_map = {}
for loc in locations:
    coords = tuple(loc.get('location', {}).get('coordinates', []))
    if len(coords) == 2:
        coord_groups[coords].append(loc)

# 2. Per ogni gruppo, calcola offset se ci sono più marker
for coords, group in coord_groups.items():
    n = len(group)
    for i, loc in enumerate(group):
        # ESTRAI thing_id PRIMA DI TUTTO
        location_id = loc.get('@iot.id', '')
        thing_id = get_thing_from_location_id(location_id)
        
        if n == 1:
            lon, lat = coords
        else:
            # Offset circolare: distribuisci i marker su un piccolo cerchio
            angle = 2 * math.pi * i / n
            radius = 0.0002  # Raggio in gradi (puoi modificarlo se necessario)
            lon = coords[0] + radius * math.cos(angle)
            lat = coords[1] + radius * math.sin(angle)
        
        # Memorizza il mapping DOPO aver calcolato le coordinate
        offset_coords_map[(round(lat, 6), round(lon, 6))] = thing_id
        
        display_name = CLASSI_NAMES.get(thing_id, thing_id)
        istituto = get_istituto_for_thing(thing_id)
        marker_color = sensor_colors.get(thing_id, '#9ca3af')
        aqi_cat = sensor_aqi_map.get(thing_id)
        
        if marker_color == '#9ca3af':
            status_text = "Offline"
        elif aqi_cat is not None:
            status_text = f"Qualità: {AIR_QUALITY_LABELS[aqi_cat]}"
        else:
            status_text = "Dati non disponibili"

        popup_html = f"""
        <div class="sensor-popup">
            <div class="popup-title">{display_name}</div>
            <div class="popup-subtitle"><strong>{thing_id}</strong></div>
            <div class="popup-subtitle">📍 {istituto}</div>
            <div class="popup-subtitle" style="color:{marker_color}; font-weight:700;">
                {status_text}
            </div>
        </div>
        """

        icon_html = f"""
        <div style="
            background:{marker_color};
            width:18px;
            height:18px;
            border-radius:50%;
            border:2px solid #ffffff;
            box-shadow:0 0 3px #333;
        ">
        </div>
        """

        try:
            folium.Marker(
                location=[lat, lon],
                popup=folium.Popup(popup_html, max_width=250),
                tooltip=display_name,
                icon=folium.DivIcon(html=icon_html)
            ).add_to(cluster)
        except Exception as e:
            continue



# Container per mappa
if 'map_data' not in st.session_state:
    st.session_state.map_data = None

st.markdown("""
    <style>
    /* Wrapper per contenere la mappa dentro horizontal block bianco */
    div[data-testid="stHorizontalBlock"]:has(.map-container-wrapper) {
        background: white !important;
        border-radius: 20px !important;
        padding: 12px !important;
        box-shadow: 0 2px 12px rgba(0,0,0,0.06) !important;
        gap: 30px !important;
        margin-bottom: -30px !important;
        margin-top: -120px !important;
        height: 650px !important;  /* NUOVO: imposta altezza fissa */
        max-height: 640px !important;  /* NUOVO: altezza massima */
        overflow: hidden !important;  /* NUOVO: nasconde overflow */
    }
    
    /* Rimuovi padding extra dalle colonne */
    div[data-testid="stHorizontalBlock"]:has(.map-container-wrapper) > div[data-testid="column"] {
        padding: 0 !important;
        margin: 0 !important;
    }
    
    .map-container-wrapper {
        width: 100%;
    }
    </style>
""", unsafe_allow_html=True)



col_map = st.columns(1)[0]

# Inserisci il logo centrato e piccolo sopra la mappa
logo_path = "assets/ediaqi_logo3.png"
if Path(logo_path).exists():
    logo_b64 = get_image_base64(logo_path)
    st.markdown(
        f"""
        <div style="width:100%; display:flex; justify-content:left;margin-left:13px; align-items:center; margin-bottom:10px; margin-top:-628px;">
            <img src="data:image/png;base64,{logo_b64}" style="height:20px;" />
        </div>
        """,
        unsafe_allow_html=True
    )

with col_map:
    # Marker per attivare lo stile
    st.markdown('<div class="map-container-wrapper">', unsafe_allow_html=True)
    
    # MOSTRA MAPPA
    map_data = st_folium(
        m,
        width=1400,
        height=600,
        key="main_map_stable", 
        returned_objects=["last_object_clicked"]
    )
    
    st.markdown('</div>', unsafe_allow_html=True)



# PANNELLO DETTAGLI SOVRAPPOSTO
if st.session_state.get('show_details', False) and st.session_state.selected_sensor is not None:
    sensor = st.session_state.selected_sensor
    thing_id = sensor['thing_id']
    location = sensor['location']
    
    display_name = CLASSI_NAMES.get(thing_id, thing_id)
    istituto = get_istituto_for_thing(thing_id)
    
    # Ottieni reference time per questo sensore
    try:
        thing = client.get_thing(thing_id)
        first_ds = client.get_datastreams(thing['@iot.id'])
        first_obs = client.get_latest_observation(first_ds[0].get('@iot.id'))
        ref_time = parse_time(first_obs.get('phenomenonTime'))
        ref_time_dt = ref_time.to_pydatetime().replace(tzinfo=None) if not pd.isna(ref_time) else None
        
        # Verifica se offline
        now = datetime.now()
        is_offline = False
        if ref_time_dt:
            time_diff = (now - ref_time_dt).total_seconds() / 3600
            is_offline = time_diff > 6
    except:
        ref_time_dt = None
        is_offline = True
    
    # NUOVO CSS PER OVERLAY SOVRAPPOSTO
    st.markdown("""
        <style>
        /* Posiziona il container dei dettagli come overlay SOPRA la mappa */
        .details-overlay-container {
            position: fixed;
            bottom: 0;
            left: 50%;
            transform: translateX(-50%);
            width: calc(100% - 100px);
            max-width: 1400px;
            z-index: 1000;
            pointer-events: none;
        }
                
        .back-button-container {
            display: flex;
            justify-content: center;
            margin-top: 0px;
            margin-bottom: 0px;
        }
        
        /* Horizontal block per i dettagli con stile uguale a widget_app */
        div[data-testid="stHorizontalBlock"]:has(.details-content-wrapper) {
            background: white !important;
            border-radius: 20px 20px 0 0 !important;
            padding: 30px !important;
            box-shadow: 0 -4px 20px rgba(0,0,0,0.15) !important;
            margin: 0 !important;
            pointer-events: auto !important;
            animation: slideUp 0.3s ease-out;
            
            /* COPRE PIÙ DELLA MAPPA (~500px su 600px = 83%) */
            min-height: 500px !important;
            max-height: 100vh !important;
            overflow-y: auto !important;
            
            /* PIÙ SOVRAPPOSTO: solleva il box di 520px */
            position: relative !important;
            margin-top: -640px !important;
        }
        
        @keyframes slideUp {
            from { transform: translateY(100%); }
            to { transform: translateY(0); }
        }
        
        /* Rimuovi padding dalle colonne interne */
        div[data-testid="stHorizontalBlock"]:has(.details-content-wrapper) > div[data-testid="column"] {
            padding: 0 !important;
            margin: 0 !important;
        }
        
        /* Pulsante chiudi */
        .close-details-btn-wrapper {
            position: absolute;
            top: 15px;
            right: 15px;
            z-index: 10;
        }
        
        /* Scrollbar personalizzata */
        div[data-testid="stHorizontalBlock"]:has(.details-content-wrapper)::-webkit-scrollbar {
            width: 8px;
        }
        
        div[data-testid="stHorizontalBlock"]:has(.details-content-wrapper)::-webkit-scrollbar-track {
            background: #f1f1f1;
            border-radius: 10px;
        }
        
        div[data-testid="stHorizontalBlock"]:has(.details-content-wrapper)::-webkit-scrollbar-thumb {
            background: #888;
            border-radius: 10px;
        }
        
        div[data-testid="stHorizontalBlock"]:has(.details-content-wrapper)::-webkit-scrollbar-thumb:hover {
            background: #555;
        }
        </style>
    """, unsafe_allow_html=True)
    
    # CONTAINER OVERLAY CON COLONNA SINGOLA
    st.markdown('<div class="details-overlay-container">', unsafe_allow_html=True)
    
    col_details = st.columns(1)[0]
    
    with col_details:
        st.markdown('<div class="details-content-wrapper">', unsafe_allow_html=True)
        
        # Header con data e pulsante chiudi
        col_header, col_close = st.columns([12, 1])
        
        with col_header:
            if ref_time_dt:
                timezone_cfg = CONFIG.get('timezone', 'Europe/Rome')
                if timezone_cfg == 'local':
                    import tzlocal
                    try:
                        timezone_cfg = str(tzlocal.get_localzone())
                    except:
                        timezone_cfg = 'Europe/Rome'
                
                import pytz
                local_tz = pytz.timezone(timezone_cfg)
                ref_ts = pd.Timestamp(ref_time_dt, tz='UTC').tz_convert(local_tz)
                
                date_formatted = ref_ts.strftime("%a, %d %B %H:%M").capitalize()
                date_formatted = date_formatted.replace("Mon", "Lun").replace("Tue", "Mar").replace("Wed", "Mer")
                date_formatted = date_formatted.replace("Thu", "Gio").replace("Fri", "Ven").replace("Sat", "Sab").replace("Sun", "Dom")
                date_formatted = date_formatted.replace("January", "gennaio").replace("February", "febbraio").replace("March", "marzo")
                date_formatted = date_formatted.replace("April", "aprile").replace("May", "maggio").replace("June", "giugno")
                date_formatted = date_formatted.replace("July", "luglio").replace("August", "agosto").replace("September", "settembre")
                date_formatted = date_formatted.replace("October", "ottobre").replace("November", "novembre").replace("December", "dicembre")
                
                # TIMEZONE LABEL (come in widget_app)
                timezone_label = ""
                if timezone_cfg == 'Europe/Rome':
                    timezone_label = '<span style="font-size:10px; color:#999; margin-left:8px;">(ora locale Ferrara)</span>'
                elif timezone_cfg == 'UTC':
                    timezone_label = '<span style="font-size:10px; color:#999; margin-left:8px;">(UTC)</span>'
                else:
                    # Per timezone custom o local, mostra il nome
                    timezone_label = f'<span style="font-size:10px; color:#999; margin-left:8px;">({timezone_cfg})</span>'
                
                warning_html = ""
                if is_offline:
                    warning_path = IMAGES.get('esclamativo')
                    if warning_path and Path(warning_path).exists():
                        warning_b64 = get_image_base64(warning_path)
                        if warning_b64:
                            warning_html = f'<img src="data:image/png;base64,{warning_b64}" style="width:20px; height:20px; margin-right:8px; vertical-align:middle;">'
                
                st.markdown(f"""
                    <div style="margin-bottom:20px;">
                        <div style="font-size:24px; font-weight:700; color:#006278; margin-bottom:8px;">
                            {display_name}
                        </div>
                        <div style="font-size:14px; color:#666; display:flex; align-items:center;">
                            {warning_html}{date_formatted} {timezone_label}
                        </div>
                        <div style="font-size:13px; color:#999; margin-top:4px;">
                            📍 {istituto}
                        </div>
                    </div>
                """, unsafe_allow_html=True)
            else:
                st.markdown(f"""
                    <div style="margin-bottom:20px;">
                        <div style="font-size:24px; font-weight:700; color:#006278;">
                            {display_name}
                        </div>
                        <div style="font-size:14px; color:#666;">Dati non disponibili</div>
                    </div>
                """, unsafe_allow_html=True)
        
        with col_close:
            st.markdown('<div class="close-details-btn-wrapper">', unsafe_allow_html=True)
            if st.button("❌", key="close_details"):
                st.session_state.close_details_clicked = True
                st.rerun()
            st.markdown('</div>', unsafe_allow_html=True)
        
        # HEATMAP
        st.markdown('<div style="margin-top:20px;">', unsafe_allow_html=True)
        st.markdown('<div style="font-size:18px; font-weight:700; color:#006278; margin-bottom:15px; border-bottom:2px solid #00d5a7; padding-bottom:5px;margin-top:-10px">Andamento Qualità Aria - Ultime 24 Ore</div>', unsafe_allow_html=True)
        
        with st.spinner("Creazione heatmap..."):
            heatmap_fig = create_categorical_heatmap(client, thing_id, standard, CONFIG.get('timezone', 'Europe/Rome'))
        
        if heatmap_fig:
            st.plotly_chart(heatmap_fig, use_container_width=True)
        else:
            st.info("Dati non disponibili per la visualizzazione dell'heatmap")
        
        st.markdown('</div>', unsafe_allow_html=True)
        
        # BOTTONI INFO
        col_details, col_adv = st.columns(2)

        with col_details:
            if st.button("🏠 Dettagli Stanza", key=f"btn_details_{thing_id}", use_container_width=True):
                show_combined_details_dialog(location, client, thing_id)

        with col_adv:
            if st.button("📊 Avanzata", key=f"btn_adv_{thing_id}", use_container_width=True):
                # Estrai l'istituto dal thing_id
                istituto_name = get_istituto_for_thing(thing_id)
                
                # NUOVI FLAG
                st.session_state.from_advanced_view = True
                st.session_state.coming_from_map = True
                
                # FORZA IL CAMBIO ISTITUTO *PRIMA* DI TUTTO
                st.session_state.force_istituto_change = True
                st.session_state.pending_istituto = istituto_name
                st.session_state.pending_classe = thing_id
                
                # Salva stato per il ritorno
                st.session_state.return_to_istituto = istituto_name
                st.session_state.return_to_classe = thing_id
                st.session_state.return_to_advanced = True
                
                # Imposta la visualizzazione avanzata e torna al widget
                st.session_state.selected_istituto = istituto_name
                st.session_state.selected_classe = thing_id
                st.session_state.advanced_view = True
                st.session_state.show_map_page = False
                st.session_state.force_back_to_dashboard = False
                
                st.rerun()
        
        st.markdown('</div>', unsafe_allow_html=True)
    
    st.markdown('</div>', unsafe_allow_html=True)

# PULSANTE TORNA ALLA DASHBOARD - SEMPRE IN FONDO
st.markdown('<div class="back-button-container">', unsafe_allow_html=True)

col_empty1, col_btn, col_empty2 = st.columns([2, 1, 2])

with col_btn:
    if st.button("← Torna alla Dashboard", use_container_width=True, key="btn_back_dashboard"):
        # RESETTA I FLAG DELLA MAPPA
        st.session_state.coming_from_map = False
        st.session_state.from_advanced_view = False
        st.session_state.map_page_just_opened = False 
        # IMPOSTA FLAG PRIMA DI TUTTO
        st.session_state.force_back_to_dashboard = True
        
        # Reset completo dello stato mappa
        st.session_state.show_details = False
        st.session_state.selected_sensor = None
        st.session_state.show_map_page = False
        st.session_state.map_page_just_opened = False
        st.session_state.close_details_clicked = False
        
        # Reset map_data per evitare re-elaborazione click
        if 'map_data' in st.session_state:
            st.session_state.map_data = None
        
        # Ripristina lo stato precedente
        if 'return_to_istituto' in st.session_state:
            st.session_state.selected_istituto = st.session_state.return_to_istituto
        if 'return_to_classe' in st.session_state:
            st.session_state.selected_classe = st.session_state.return_to_classe
        if 'return_to_advanced' in st.session_state:
            st.session_state.advanced_view = st.session_state.return_to_advanced  
        
        st.rerun()


# ELABORA SEMPRE I CLICK SUI SENSORI
if not st.session_state.get('force_back_to_dashboard', False):
    if map_data and map_data.get("last_object_clicked") not in (None, {}):
        clicked_coords = map_data['last_object_clicked']
        
        sensor_found = False
        clicked_lat = round(clicked_coords['lat'], 6)
        clicked_lon = round(clicked_coords['lng'], 6)
        
        # CERCA PRIMA NEL MAPPING OFFSET
        thing_id = offset_coords_map.get((clicked_lat, clicked_lon))
        
        if thing_id:
            # Trova la location corrispondente
            for loc in locations:
                location_id = loc.get('@iot.id', '')
                if get_thing_from_location_id(location_id) == thing_id:
                    current_sensor = st.session_state.get('selected_sensor') or {}
                    
                    # Se è lo stesso sensore ma i dettagli sono chiusi, riaprili
                    if current_sensor.get('thing_id') != thing_id or not st.session_state.get('show_details', False):
                        st.session_state.selected_sensor = {
                            'thing_id': thing_id,
                            'location': loc
                        }
                        st.session_state.show_details = True
                        sensor_found = True
                        st.rerun()
                    break


st.markdown('</div>', unsafe_allow_html=True)

