import os
import json
import streamlit as st
import pandas as pd
from PIL import Image, ImageDraw
from pathlib import Path
from streamlit_drawable_canvas import st_canvas
import time

def show_mapper(cfg):
    # --- 1. CONFIGURAZIONE PERCORSI ---
    MAPS_DIR = Path(cfg['maps']['map_dir'])
    SAMPLES_DIR = Path(cfg['train']['samples_dir'])
    PENDING_DIR = Path(cfg['collect_train']['jobs_dir']) / "pending"
    BEACONS_FILE = "/data/config/beacons.csv"

    [p.mkdir(parents=True, exist_ok=True) for p in [MAPS_DIR, SAMPLES_DIR, PENDING_DIR]]

    def load_map_metadata(f_id):
        meta_path = MAPS_DIR / f"{cfg['maps']['meta_prefix']}{f_id}.json"
        defaults = {"pixel_ratio": 1.0, "calibrated": False, "origin": [0, 0], "grid_size": 50}
        if meta_path.exists():
            with open(meta_path, "r") as f: return {**defaults, **json.load(f)}
        return defaults

    st.subheader("🗺️ Gestione Mappatura e Rilevamento")

    # Selezione Piano
    maps = sorted([f.replace(cfg['maps']['floor_prefix'], "").split('.')[0] for f in os.listdir(MAPS_DIR) if f.startswith(cfg['maps']['floor_prefix'])])
    if not maps: st.error("Nessuna mappa trovata."); return
    floor_id = st.selectbox("Seleziona Piano (Z):", maps)
    meta = load_map_metadata(floor_id)

    # --- 2. STATO SISTEMA ---
    c_s1, c_s2 = st.columns(2)
    with c_s1:
        st.info(f"📏 Scala: {'✅' if meta['calibrated'] else '❌'} ({meta['pixel_ratio']:.4f} px/cm)")
    with c_s2:
        st.info(f"🎯 Origine: {'✅' if meta['origin'] != [0,0] else '❌'} (X:{meta['origin'][0]}, Y:{meta['origin'][1]})")

    # --- 3. CONTROLLI VISUALIZZAZIONE ---
    with st.expander("🎨 Opzioni Visualizzazione", expanded=True):
        c_v1, c_v2, c_v3 = st.columns(3)
        zoom = c_v1.slider("🔍 Zoom Mappa", 0.1, 4.0, 1.0, 0.1)
        dot_size = c_v2.slider("🔵/🟢 Dimensione Punti", 10, 100, 40)
        mode = c_v3.radio("Modalità Interazione:", ["🖐️ NAVIGA", "🎯 AZIONE"], horizontal=True)

    # --- 4. SELEZIONE STRUMENTO ---
    t1, t2, t3 = st.columns(3)
    if t1.button("📏 IMPOSTA SCALA", use_container_width=True): st.session_state.map_tool = "Calibra"
    if t2.button("🎯 SET ORIGINE", use_container_width=True): st.session_state.map_tool = "Origine"
    
    is_ready = meta.get("calibrated", False) and meta["origin"] != [0, 0]
    if t3.button("📡 RILEVA", use_container_width=True, disabled=not is_ready): st.session_state.map_tool = "Rileva"

    tool = st.session_state.get('map_tool', 'Rileva')
    st.write(f"Strumento attivo: **{tool}**")

    # --- 5. PREPARAZIONE IMMAGINE E STORICO ---
    img_path = MAPS_DIR / f"{cfg['maps']['floor_prefix']}{floor_id}.png"
    if not img_path.exists(): img_path = MAPS_DIR / f"{cfg['maps']['floor_prefix']}{floor_id}.jpg"
    img = Image.open(img_path).convert("RGBA")
    draw = ImageDraw.Draw(img)

    if is_ready:
        samples_files = list(SAMPLES_DIR.glob(f"{floor_id}_*.csv"))
        pending_files = list(PENDING_DIR.glob(f"{floor_id}_*.csv"))
        
        def draw_points(files, color):
            for f in files:
                try:
                    p = f.stem.split("_")
                    px = (int(p[1]) * meta["pixel_ratio"]) + meta["origin"][0]
                    py = (int(p[2]) * meta["pixel_ratio"]) + meta["origin"][1]
                    r = dot_size // 2
                    draw.ellipse([px-r, py-r, px+r, py+r], fill=color, outline="white", width=2)
                except: continue

        draw_points(samples_files, "#228B22") # Verde: Completati
        draw_points(pending_files, "#0000FF") # Blu: In corso

    # --- 6. CANVAS ---
    d_mode = "transform" if mode == "🖐️ NAVIGA" else ("line" if tool == "Calibra" else "point")
    
    canvas_result = st_canvas(
        background_image=img,
        height=int(img.size[1] * zoom),
        width=int(img.size[0] * zoom),
        drawing_mode=d_mode,
        display_toolbar=True,
        update_streamlit=True,
        key=f"canvas_v10_{floor_id}_{zoom}_{mode}_{tool}",
    )

    # --- 7. LOGICA AZIONI E SALVATAGGIO CSV ---
    if mode == "🎯 AZIONE" and canvas_result.json_data and canvas_result.json_data["objects"]:
        last = canvas_result.json_data["objects"][-1]
        raw_x, raw_y = last["left"] / zoom, last["top"] / zoom

        if tool == "Calibra" and last["type"] == "line":
            px_dist = ((last["x2"] - last["x1"])**2 + (last["y2"] - last["y1"])**2)**0.5 / zoom
            dist_cm = st.number_input("Distanza reale (cm):", value=100.0)
            if st.button("APPLICA SCALA"):
                meta.update({"pixel_ratio": px_dist / dist_cm, "calibrated": True})
                with open(MAPS_DIR / f"{cfg['maps']['meta_prefix']}{floor_id}.json", "w") as f:
                    json.dump(meta, f)
                st.rerun()

        elif tool == "Origine":
            if st.button(f"Fissa Origine qui: {int(raw_x)}, {int(raw_y)}"):
                meta["origin"] = [int(raw_x), int(raw_y)]
                with open(MAPS_DIR / f"{cfg['maps']['meta_prefix']}{floor_id}.json", "w") as f:
                    json.dump(meta, f)
                st.rerun()

        elif tool == "Rileva" and is_ready:
            dx = (raw_x - meta["origin"][0]) / meta["pixel_ratio"]
            dy = (raw_y - meta["origin"][1]) / meta["pixel_ratio"]
            grid = meta.get("grid_size", 50)
            sx, sy = int(round(dx/grid)*grid), int(round(dy/grid)*grid)
            
            st.write(f"### 📍 Punto: {sx}cm, {sy}cm")
            
            if os.path.exists(BEACONS_FILE):
                b_df = pd.read_csv(BEACONS_FILE, sep=";")
                sel_b = st.selectbox("Seleziona Beacon:", b_df.apply(lambda x: f"{x['BeaconName']} | {x['MAC']}", axis=1))
                if st.button("🚀 REGISTRA LETTURA", type="primary", use_container_width=True):
                    b_name, b_mac = sel_b.split(" | ")
                    fname = f"{floor_id}_{sx}_{sy}.csv"
                    
                    # --- FIX SINTASSI CSV ---
                    # Formato: Position;Floor;RoomName;X;Y;Z;BeaconName;MAC
                    data_out = {
                        "Position": f"P_{sx}_{sy}",
                        "Floor": floor_id,
                        "RoomName": "Area_Rilevazione",
                        "X": sx,
                        "Y": sy,
                        "Z": 0,
                        "BeaconName": b_name,
                        "MAC": b_mac
                    }
                    pd.DataFrame([data_out]).to_csv(PENDING_DIR / fname, index=False, sep=";")
                    st.toast(f"Punto Blu registrato!")
                    time.sleep(1); st.rerun()
