"""
FROST Widgets Module
Componenti di visualizzazione riutilizzabili
"""

import streamlit as st
from frost_utils import format_value, format_timestamp, detect_measure, get_datastream_config, classify_value
from frost_client import parse_time
import pandas as pd
from datetime import datetime



def render_thing_header(thing, timezone='Europe/Rome'):
    """Renderizza header Thing"""
    st.markdown(f"""
    <div class="thing-header">
        <div class="thing-title">{thing['name']}</div>
        <div class="thing-desc">{thing.get('description', 'No description')}</div>
    </div>
    """, unsafe_allow_html=True)


def render_reference_time(reference_time, timezone='Europe/Rome', timezone_real_name='Europe/Rome'):
    """Renderizza badge reference time"""
    if not reference_time:
        return
    
    if isinstance(reference_time, pd.Timestamp):
        latest_utc = reference_time
    else:
        latest_utc = pd.Timestamp(reference_time, tz='UTC')
    
    date_str = format_timestamp(latest_utc, timezone_real_name)
    
    if timezone == 'local':
        tz_label = f"Client Local – {timezone_real_name}"
    else:
        tz_label = timezone_real_name
    
    st.markdown(
        f'<div class="update-badge">Reference Time: {date_str} ({tz_label})</div>',
        unsafe_allow_html=True
    )


def process_datastreams_data(client, thing_id, datastreams, standard=None, reference_time=None):
    """
    Processa datastreams e restituisce dati formattati per visualizzazione
    
    Returns:
        tuple: (with_thresh, without_thresh, ds_map, latest_time)
    """
    cat_labels = []
    cat_colors = []
    alias_idx = {}
    datastream_labels = []
    n_cat = 1
    
    if standard:
        cat_labels = standard.get("categoryLabels", [])
        cat_colors = standard.get("categoryColors", [])
        datastream_labels = standard.get("datastreamLabels", [])
        from frost_utils import build_alias_index
        alias_idx = build_alias_index(standard)
        n_cat = len(cat_labels) if cat_labels else 1
    
    with_thresh = []
    without_thresh = []
    ds_map = {}
    latest = reference_time
    
    for idx, ds in enumerate(datastreams):
        ds_id = ds.get('@iot.id')
        name = ds.get('name') or ""
        uom = (ds.get('unitOfMeasurement') or {}).get('symbol') or (ds.get('unitOfMeasurement') or {}).get('name') or ""
        
        observations = ds.get('Observations', [])

        # Cerca osservazione PIÙ VICINA e <= reference_time
        if reference_time:
            ref_obs = client.get_observations_timerange(
                ds_id, 
                hours_back=2, 
                limit=50,     
                reference_time=reference_time,
                select_clause='phenomenonTime,result'
            )
            
            if ref_obs:
                # filtra solo osservazioni <= reference_time
                ref_time_naive = reference_time.replace(tzinfo=None) if hasattr(reference_time, 'tzinfo') else reference_time
                
                valid_obs = []
                for o in ref_obs:
                    obs_time = parse_time(o.get('phenomenonTime'))
                    if not pd.isna(obs_time):
                        obs_time_naive = obs_time.to_pydatetime().replace(tzinfo=None)
                        if obs_time_naive <= ref_time_naive:
                            valid_obs.append(o)
                
                if valid_obs:
                    # Trova la più vicina tra quelle VALIDE
                    ref_obs_sorted = sorted(
                        valid_obs,
                        key=lambda o: abs((parse_time(o.get('phenomenonTime')).to_pydatetime().replace(tzinfo=None) - ref_time_naive).total_seconds())
                    )
                    obs = ref_obs_sorted[0]
                else:
                    obs = None
            else:
                obs = None
        
        if not obs:
            ds_map[idx] = {'id': ds_id, 'name': name, 'unit': uom}
            without_thresh.append({
                "name": name or "Unknown",
                "value": None,
                "unit": uom,
                "ts": reference_time if reference_time else pd.NaT,
                "ds_idx": idx,
                "no_data": True
            })
            continue
        
        ts = parse_time(obs.get('phenomenonTime'))
        val = obs.get('result')
        
        if pd.isna(ts):
            ds_map[idx] = {'id': ds_id, 'name': name, 'unit': uom}
            without_thresh.append({
                "name": name or "Unknown",
                "value": None,
                "unit": uom,
                "ts": reference_time if reference_time else pd.NaT,
                "ds_idx": idx,
                "no_data": True
            })
            continue
        
        ts_naive = ts.to_pydatetime().replace(tzinfo=None) if not pd.isna(ts) else None
        latest_naive = latest.replace(tzinfo=None) if latest and isinstance(latest, datetime) else latest
        
        if ts_naive and (latest_naive is None or ts_naive > latest_naive):
            latest = ts_naive
        elif latest_naive:
            latest = latest_naive
        
        ds_map[idx] = {'id': ds_id, 'name': name, 'unit': uom}
        
        if standard and alias_idx:
            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:
                ds_config = get_datastream_config(detected_name, datastream_labels)
                
                if ds_config:
                    display_name = ds_config.get("displayLabel", name)
                    unit = uom
                    th = ds_config.get("categoryThresholds", []) or []
                    greater_worse = bool(ds_config.get("greaterIsWorse", True))
                
                    if th:
                        cat, prog = classify_value(val, th, greater_worse, n_cat)
                        cat_name = cat_labels[cat] if (cat_labels and cat is not None and cat < len(cat_labels)) else "N/A"
                        color = cat_colors[cat] if (cat_colors and cat is not None and cat < len(cat_colors)) else "#888"
                        
                        with_thresh.append({
                            "name": display_name,
                            "value": val,
                            "unit": unit,
                            "ts": ts,
                            "cat_name": cat_name,
                            "color": color,
                            "progress": prog,
                            "ds_idx": idx
                        })
                        continue
                    else:
                        without_thresh.append({
                            "name": display_name,
                            "value": val,
                            "unit": unit,
                            "ts": ts,
                            "ds_idx": idx
                        })
                        continue
        
        without_thresh.append({
            "name": name or "Unknown",
            "value": val,
            "unit": uom,
            "ts": ts,
            "ds_idx": idx
        })
    
    return with_thresh, without_thresh, ds_map, latest


def render_datastreams_widget(with_thresh, without_thresh, ds_map, show_chart_button=True):
    """
    Renderizza widget a barre con datastreams
    
    Args:
        with_thresh: Lista items con threshold
        without_thresh: Lista items senza threshold
        ds_map: Mapping indice -> info datastream
        show_chart_button: Se mostrare bottone grafico
    """
    all_items = []
    
    for item in without_thresh:
        all_items.append({
            'type': 'simple',
            'name': item['name'],
            'value': item.get('value'),
            'unit': item.get('unit', ''),
            'ts': item.get('ts'),
            'ds_idx': item['ds_idx'],
            'no_data': item.get('no_data', False)
        })
    
    for item in with_thresh:
        all_items.append({
            'type': 'threshold',
            'name': item['name'],
            'value': item['value'],
            'unit': item['unit'],
            'ts': item['ts'],
            'ds_idx': item['ds_idx'],
            'cat_name': item['cat_name'],
            'color': item['color'],
            'progress': item['progress']
        })
    
    all_items_sorted = sorted(all_items, key=lambda x: (x['type'] == 'threshold', x['name'].lower()))
    
    for item in all_items_sorted:
        ds_info = ds_map.get(item['ds_idx'])
        
        if show_chart_button:
            col_main, col_btn = st.columns([20, 1])
        else:
            col_main = st.container()
            col_btn = None
        
        with col_main:
            if item['type'] == 'simple':
                if item.get('no_data'):
                    value_display = "no data available for this reference time"
                else:
                    value_display = f"{format_value(item['value'])} {item['unit']}"
                
                progress = 1.0
                color = 'var(--neutral-bar)'
                
                st.markdown(f"""
                <div class="progress-item">
                    <div class="progress-header">
                        <span class="progress-label">{item['name']}</span>
                        <div class="progress-info">
                            <span class="progress-value">{value_display}</span>
                        </div>
                    </div>
                    <div class="progress-bar-bg">
                        <div class="progress-bar-fill" style="width:{progress*100:.1f}%;background:{color};"></div>
                    </div>
                </div>
                """, unsafe_allow_html=True)
            else:
                st.markdown(f"""
                <div class="progress-item">
                    <div class="progress-header">
                        <span class="progress-label">{item['name']}</span>
                        <div class="progress-info">
                            <span class="progress-value">{format_value(item['value'])} {item['unit']}</span>
                            <span class="progress-badge" style="background:{item['color']};color:white;">{item['cat_name']}</span>
                        </div>
                    </div>
                    <div class="progress-bar-bg">
                        <div class="progress-bar-fill" style="width:{item['progress']*100:.1f}%;background:{item['color']};"></div>
                    </div>
                </div>
                """, unsafe_allow_html=True)
        
        if col_btn and ds_info:
            with col_btn:
                if st.button("📊", key=f"chart_{item['ds_idx']}", help=f"Show chart for {item['name']}"):
                    st.session_state.show_chart = True
                    st.session_state.chart_datastream = ds_info
                    st.rerun()
    
    if not all_items:
        st.info("No data available")

def render_thing_information_section(client, thing_id):
    """Renderizza sezione informazioni Location e FeaturesOfInterest del Thing"""
    from frost_utils import get_thing_locations, get_thing_features_of_interest
    import plotly.graph_objects as go
    
    col1, col2 = st.columns([20, 0.5])
    with col1:
        st.markdown("### Thing Information")
    with col2:
        if st.session_state.show_map:
            if st.button("✕", key="close_map_button", help="Close map"):
                st.session_state.show_map = False
                st.session_state.map_location_idx = None
                st.rerun()
        
    # Placeholder per la mappa (sopra i tab)
    map_placeholder = st.empty()
    
    # Tab per Locations e FeaturesOfInterest
    tab1, tab2 = st.tabs(["Locations", "Features of Interest"])
    
    with tab1:
        with st.spinner("Loading locations..."):
            locations = get_thing_locations(client, thing_id)
        
        if locations:
            for idx, loc in enumerate(locations):
                with st.expander(f"{loc.get('name', 'Unknown Location')}", expanded=(idx == 0)):
                    location = loc.get('location', {})
                    coords = None
                    if location.get('type') == 'Point':
                        coords = location.get('coordinates', [])
                    
                    desc = loc.get('description', '—')
                    st.markdown(f"**Description:**")
                    st.markdown(f"<div style='white-space: pre-wrap; word-wrap: break-word;'>{desc}</div>", unsafe_allow_html=True)
                    
                    col1, col2 = st.columns([1, 1])
                    
                    with col1:
                        st.markdown(f"**Encoding:** {loc.get('encodingType', '—')}")
                    
                    with col2:
                        if coords and len(coords) >= 2:
                            st.markdown(f"**Coordinates:** {coords[1]}, {coords[0]}")
                            if st.button("🗺️ Show on Map", key=f"map_btn_{idx}"):
                                # Crea mappa con Plotly
                                fig = go.Figure(go.Scattermapbox(
                                    lat=[coords[1]],
                                    lon=[coords[0]],
                                    mode='markers',
                                    marker=go.scattermapbox.Marker(size=14, color='red'),
                                    text=[loc.get('name', 'Location')],
                                    hoverinfo='text'
                                ))
                                
                                fig.update_layout(
                                    mapbox=dict(
                                        style="open-street-map",
                                        center=dict(lat=coords[1], lon=coords[0]),
                                        zoom=15
                                    ),
                                    height=400,
                                    margin=dict(l=0, r=0, t=0, b=0)
                                )
                                
                                with map_placeholder:
                                    st.markdown("#### 📍 Location Map")
                                    st.plotly_chart(fig, use_container_width=True, key=f"map_loc_{thing_id}_{idx}")
                        else:
                            st.markdown("**Coordinates:** Not available")
                    
                    props = loc.get('properties', {})
                    if props:
                        st.markdown("---")
                        st.markdown("**Properties:**")
                        _render_properties_tree(props)
        else:
            st.info("No locations available")
    
    with tab2:
        with st.spinner("Loading features of interest..."):
            features = get_thing_features_of_interest(client, thing_id)
        
        if features:
            for idx, feat in enumerate(features):
                with st.expander(f"{feat.get('name', 'Unknown Feature')}", expanded=(idx == 0)):
                    feature = feat.get('feature', {})
                    coords = None
                    if feature.get('type') == 'Point':
                        coords = feature.get('coordinates', [])
                    
                    desc = feat.get('description', '—')
                    st.markdown(f"**Description:**")
                    st.markdown(f"<div style='white-space: pre-wrap; word-wrap: break-word;'>{desc}</div>", unsafe_allow_html=True)
                    
                    col1, col2 = st.columns([1, 1])
                    
                    with col1:
                        st.markdown(f"**Encoding:** {feat.get('encodingType', '—')}")
                    
                    with col2:
                        if coords and len(coords) >= 2:
                            st.markdown(f"**Coordinates:** {coords[1]}, {coords[0]}")
                        else:
                            st.markdown("**Coordinates:** Not available")
                                        
                    props = feat.get('properties', {})
                    if props:
                        st.markdown("---")
                        st.markdown("**Properties:**")
                        _render_properties_tree(props)
        else:
            st.info("No features of interest available")

def _render_properties_tree(props, level=0):
    """Renderizza proprietà in modo gerarchico"""
    for key, value in props.items():
        if isinstance(value, dict):
            # Proprietà annidate partono CHIUSE (expanded=False)
            with st.expander(f"**{key}**", expanded=False):
                _render_properties_tree(value, level + 1)
        elif isinstance(value, list):
            if value and isinstance(value[0], dict):
                # Liste di dizionari partono CHIUSE (expanded=False)
                with st.expander(f"📋 **{key}** ({len(value)} items)", expanded=False):
                    for i, item in enumerate(value):
                        st.markdown(f"**Item {i + 1}:**")
                        if isinstance(item, dict):
                            _render_properties_tree(item, level + 2)
                        else:
                            st.write(item)
            else:
                st.markdown(f"**{key}:** `{value}`")
        else:
            st.markdown(f"**{key}:** `{value if value is not None else '—'}`")

def get_common_styles():
    """Restituisce CSS comune per le applicazioni"""
    return """
<style>
    @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
    
    * { font-family: 'Inter', sans-serif; }
    
    
    :root {
        --bg-primary: #212234;
        --bg-secondary: #303146;
        --bg-tertiary: #1a1c2b;
        --border: #1a1c2b;
        --text-primary: #eaf3e8;
        --text-secondary: #2c5f7f;
        --text-muted: #5a8aa3;
        --accent: #24417e;
        --accent-hover: #1d4ed8;
        --neutral-bar: #4a5568;

        /* Variabili aggiuntive */
        --button-bg: #24417e;
        --button-bg-hover: #1d4ed8;
        --button-text: #fff;
        --button-active: #e53e3e;
        --select-bg: #212234;
        --select-text: #eaf3e8;
        --select-option-bg: #303146;
        --select-option-text: #eaf3e8;
        --input-bg: #303146;
        --input-text: #eaf3e8;
        --checkbox-accent: #24417e;
    }

    
    .stApp { background: var(--bg-primary); }
    .main { padding: 1rem; }

    .block-container { 
        padding-top: 2rem !important;  /* Aumenta da 1rem a 2rem */
        max-width: 2000px; 
    }   
        
    h1 { color: var(--text-primary); font-size: 1.75rem; font-weight: 700; margin-bottom: 1.5rem; }
    h2, h3 { color: var(--text-primary); font-weight: 600; margin: 0.5rem 0; }
    
    .stTextInput input, .stNumberInput input, .stSelectbox div[data-baseweb="select"] {
        background: var(--bg-secondary) !important;
        border: 1px solid var(--border) !important;
        border-radius: 6px;
        color: var(--text-primary) !important;
        font-size: 0.875rem;
    }
    
    .stTextInput input:focus, .stNumberInput input:focus {
        border-color: var(--accent) !important;
        box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.2);
    }
    
   .stTextInput label, .stNumberInput label, .stSelectbox label, .stCheckbox label {
        color: var(--text-secondary) !important;
        font-weight: 500 !important;
        font-size: 0.875rem !important;
    }
    
    /* Fix descrizione Things negli expander - FORZATO */
    div[data-testid="stExpander"] {
        overflow: visible !important;
    }
    
    div[data-testid="stExpander"] summary {
        white-space: normal !important;
        word-wrap: break-word !important;
        overflow-wrap: break-word !important;
        overflow: visible !important;
        text-overflow: clip !important;
        max-width: 100% !important;
    }
    
    div[data-testid="stExpander"] summary p,
    div[data-testid="stExpander"] summary div,
    div[data-testid="stExpander"] summary span {
        white-space: normal !important;
        word-wrap: break-word !important;
        overflow-wrap: break-word !important;
        overflow: visible !important;
        text-overflow: clip !important;
    }
    
    div[data-testid="stExpander"] [data-testid="stMarkdownContainer"] {
        white-space: normal !important;
        word-wrap: break-word !important;
        overflow: visible !important;
    }



    .stButton button {
        background: var(--accent);
        color: white;
        border: none;
        border-radius: 6px;
        padding: 0.5rem 1.25rem;
        font-weight: 500;
        font-size: 0.875rem;
        transition: all 0.2s;
    }
    
    .stButton button:hover {
        background: var(--accent-hover);
        box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
    }
    
    .thing-header {
        background: var(--bg-secondary);
        border: 1px solid var(--border);
        border-radius: 8px;
        padding: 1.5rem;
        margin-bottom: 1rem;
    }
    
    .thing-title {
        font-size: 1.125rem;
        font-weight: 600;
        color: var(--text-primary);
        margin: 0 0 0.25rem 0;
    }
    
    .thing-desc {
        font-size: 0.875rem;
        color: var(--text-muted);
        margin: 0;
    }
    
    div[data-testid="stDecoration"] { display: none !important; }
    div[data-testid="stStatusWidget"] { display: none !important; }
    
    .update-badge {
        display: inline-block;
        background: var(--bg-secondary);
        border: 1px solid var(--border);
        padding: 0.75rem 1.25rem;
        border-radius: 8px;
        font-size: 0.95rem;
        color: var(--text-primary);
        margin-top: 0.5rem;
        font-weight: 500;
    }
    
    .progress-item {
        margin-bottom: 0.75rem;
        padding-bottom: 0.75rem;
        border-bottom: 1px solid var(--border);
        cursor: pointer;
        transition: all 0.2s;
    }
    
    .progress-item:last-child {
        margin-bottom: 0;
        padding-bottom: 0;
        border-bottom: none;
    }
    
    .progress-item:hover {
        background: var(--bg-tertiary);
        margin-left: -0.5rem;
        margin-right: -0.5rem;
        padding-left: 0.5rem;
        padding-right: 0.5rem;
        border-radius: 6px;
    }
    
    .progress-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 0.5rem;
    }
    
    .progress-label {
        font-size: 0.8rem;
        font-weight: 500;
        color: var(--text-primary);
    }
    
    .progress-info {
        display: flex;
        align-items: center;
        gap: 0.5rem;
    }
    
    .progress-value {
        font-size: 0.8rem;
        font-weight: 600;
        color: var(--text-primary);
    }
    
    .progress-badge {
        font-size: 0.65rem;
        font-weight: 600;
        padding: 0.2rem 0.5rem;
        border-radius: 4px;
        text-transform: uppercase;
    }
    
    .progress-bar-bg {
        width: 100%;
        height: 4px;
        background: var(--border);
        border-radius: 2px;
        overflow: hidden;
        margin-bottom: 0.25rem;
    }
    
    .progress-bar-fill {
        height: 100%;
        border-radius: 2px;
        transition: width 0.5s ease;
    }

    .info-button {
        cursor: pointer;
        font-size: 1.5rem;
        opacity: 0.6;
        transition: opacity 0.2s;
    }

    .info-button:hover {
        opacity: 1;
    }
    
    #MainMenu, footer { visibility: hidden; }
    .block-container { padding-top: 1rem; max-width: 1400px; }
</style>
"""







# :)