import json
import csv
import mimetypes
from logging import exception
from pathlib import Path

from django.shortcuts import render, redirect
#from .forms import RilieviForm
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib import messages
from django.shortcuts import render
from .forms import (
    AziendaForm,
    UserForm,
    UserProfileForm,
    RilieviFormInput,
    AdminRilieviFormInput,
    DeactivateUserForm,
    ReactivateUserForm,
    ReassignRilieviForm,
)  # , RilieviElaboratiForm
from .models import Azienda, Rilievi, UserProfile #RilieviElaborati,
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.core import serializers
from django.http import HttpResponseRedirect
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
from django.contrib.auth.forms import UserCreationForm, PasswordChangeForm
from django.contrib.auth import update_session_auth_hash
from django.utils.translation import gettext as _
from django.urls import reverse
from .forms import RilieviFormOutput  # RilieviForm, RilieviElaboratiForm
from .models import Rilievi, Azienda, UserProfile
from django.views.decorators.csrf import csrf_protect
from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth.models import User
from .forms import AziendaForm, UserForm, UserProfileForm
from .models import AccessLog
from django.utils import timezone
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.http import HttpResponse
import os
from django.utils.encoding import iri_to_uri
from django.db import transaction

@login_required()
@csrf_protect
def download_file(request, rilievo_id, aziendaa):
    # Percorso del file che vuoi far scaricare
    '''print(path.split('/'))
    path = path.split('/')'''
   # print(rilievo_id, azienda.pk, request.user)
    azienda = Azienda.objects.get(nome_azienda=aziendaa)
    if not request.user.is_superuser:
        rilievo = Rilievi.objects.get(pk=rilievo_id, user=request.user, azienda=azienda.pk)
    elif request.user.is_superuser:
        rilievo = Rilievi.objects.get(pk=rilievo_id, azienda=azienda.pk)

   # print(rilievo_id, azienda.pk, request.user)
   # rilievo = Rilievi.objects.get(pk=rilievo_id, user=request.user, azienda=azienda.pk)
    #print(rilievo.file_input.url)
    #{{ rilievo.file_input.url }}
    '''file_path = 'percorso/assoluto/o/relativo/al/tuo_file.pdf'''
    file_path = rilievo.file_input.path
    file_name = os.path.basename(file_path)
    ctype, _ = mimetypes.guess_type(file_name)
    if not ctype:
        ctype = "application/octet-stream"
    # Apertura del file in modalità binaria
    # with open(rilievo.file_input.path, 'rb') as f:
    #     file_data = f.read()

    # Creazione della response HTTP
    response = HttpResponse(content_type='application/zip')
    response["X-Sendfile"] = file_path
    # Impostiamo gli header in modo che il browser forzi il download
    response['Content-Disposition'] = f'attachment; filename="{file_name}"'
    return response

@login_required()
@csrf_protect
def download_fileo(request, rilievo_id, aziendaa):
    # Percorso del file che vuoi far scaricare
    '''print(path.split('/'))
    path = path.split('/')'''
    #print(rilievo_id)
    azienda = Azienda.objects.get(nome_azienda=aziendaa)
    if not request.user.is_superuser:
        rilievo = Rilievi.objects.get(pk=rilievo_id, user=request.user, azienda=azienda.pk)
    elif request.user.is_superuser:
        rilievo = Rilievi.objects.get(pk=rilievo_id, azienda=azienda.pk)
   # rilievo = Rilievi.objects.get(pk=rilievo_id, user=request.user, azienda=azienda.pk)
    #print(rilievo.file_input.url)
    #{{ rilievo.file_input.url }}
    '''file_path = 'percorso/assoluto/o/relativo/al/tuo_file.pdf'''
    file_path = rilievo.file_output.path
    file_name = os.path.basename(file_path)
    ctype, _ = mimetypes.guess_type(file_name)
    if not ctype:
        ctype = "application/octet-stream"
    #print(file_name)
    # Apertura del file in modalità binaria
    # with open(rilievo.file_output.path, 'rb') as f:
    #    file_data = f.read()

    # Creazione della response HTTP
    response = HttpResponse(content_type='application/zip')
    quoted = iri_to_uri(file_name)
    response["X-Sendfile"] = file_path
    # Impostiamo gli header in modo che il browser forzi il download
    response['Content-Disposition'] = f'attachment; filename="{file_name}"'
    return response

# Funzione per ottenere l'indirizzo IP del client
def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip

@csrf_protect
def login_view(request):
    if request.user.is_authenticated:
        next_page = request.GET.get('next', 'home')
        return redirect(next_page)

    if request.method == "POST":
        email = request.POST.get('email')
        password = request.POST.get('password')
        # Autentica l'utente
        user = authenticate(request, username=email, password=password)
        if user is not None:
            login(request, user)
            
            # Registra l'accesso
            ip_address = get_client_ip(request)  # Ottieni l'IP dell'utente
            AccessLog.objects.create(user=user, login_time=timezone.now(), ip_address=ip_address)

            # Controlla se l'utente è un superuser (admin)
            print(user.is_superuser)
            if user.is_superuser:
                return redirect('amministrazione')  # Reindirizza alla pagina amministrazione
            else:
                return redirect('home')  # Reindirizza alla pagina home per gli altri utenti
        else:
            # Login fallito, passa un messaggio di errore al template
            return render(request, 'events/login_modern.html', {'error': 'Credenziali non valide'})
    else:
        return render(request, 'events/login_modern.html')

def map3(request):
    return render(request, 'events/mappa.html')
'''@login_required
def home(request):
    return render(request, 'events/home.html', {})'''
@login_required
def home(request):
    # Ottieni l'azienda dell'utente loggato
    if not request.user.is_authenticated:
        redirect('login')
    if request.user.is_superuser:
        return redirect('amministrazione')

    azienda = request.user.userprofile.azienda

    if request.method == 'POST':
        form = RilieviFormInput(request.POST, request.FILES)
        print(request.POST)
        print(request.FILES)
        if form.is_valid():
            print('request.FILES')
            rilievo = form.save(commit=False)
            rilievo.nome_file = rilievo.file_input.name
            rilievo.user = request.user  # Salva l'utente loggato
            rilievo.azienda = azienda  # Salva l'azienda dell'utente loggato
            rilievo.save()
            
            # Calcola la dimensione del file caricato in GB
            if rilievo.file_input:
                file_size_bytes = rilievo.file_input.size
                file_size_gb = file_size_bytes / (1024 ** 3)  # Converti bytes in GB
                rilievo.dimensione = file_size_gb
                rilievo.save()
                
                # Aggiorna il totale GB caricati dell'azienda
                if azienda:
                    try:
                        azienda.giga_elab = float(azienda.giga_elab or 0) + file_size_gb
                        azienda.save()
                    except Exception as e:
                        print(f"Errore nell'aggiornamento giga_elab: {e}")
            
            messages.success(request, 'Rilievo caricato con successo!')
            
            # Invia notifica email a tutti gli admin
            admin_users = User.objects.filter(is_superuser=True)
            admin_emails = [admin.email for admin in admin_users if admin.email]
            
            if admin_emails:
                oggetto = f"Rilievo caricato da {azienda.nome_azienda}"
                testo = f"""È stato caricato un nuovo rilievo:

Azienda: {azienda.nome_azienda}
Nome rilievo: {rilievo.nome_rilievo}
Tipologia: {rilievo.get_survey_type_display()}
Utente: {request.user.first_name} {request.user.last_name} ({request.user.email})
Data caricamento: {rilievo.created_at_input.strftime('%d/%m/%Y alle %H:%M')}

Puoi visualizzare i dettagli nella sezione amministrazione del portale."""
                
                invia_email(oggetto=oggetto, testo=testo, destinatari=admin_emails)

            form = RilieviFormInput()
            return HttpResponseRedirect('/home/')
        else:
            print(form.errors)
            messages.error(request, 'Errore nel caricamento del rilievo.')
    else:
        form = RilieviFormInput()

    # Recupera i rilievi in base al flag privacy_mode dell'azienda
    if azienda and azienda.privacy_mode:
        # Modalità privacy attiva: ogni utente vede solo i propri rilievi
        rilievi_list = Rilievi.objects.filter(user=request.user).order_by('-created_at_input')
    else:
        # Modalità privacy disattiva: tutti gli utenti vedono tutti i rilievi dell'azienda
        rilievi_list = Rilievi.objects.filter(azienda=azienda).order_by('-created_at_input') if azienda else []

    return render(request, 'events/home_new.html', {
        'form': form,
        'rilievi_list': rilievi_list,
    })

@login_required
def djangologout (request):
  logout(request)
  return HttpResponseRedirect(reverse('login'))



'''@login_required
def upload_file(request):
    if request.method == 'POST':
        form = RilieviForm(request.POST, request.FILES)
        if form.is_valid():
            rilievi = form.save(commit=False)
            rilievi.nome_file = rilievi.file.name
            rilievi.user = request.user  # Assegna l'utente loggato
            rilievi.azienda = request.azienda
            rilievi.save()
            return redirect('list_uploaded_files')  # Reindirizza a una vista che mostra i file caricati
    else:
        form = RilieviForm()
    return render(request, 'upload.html', {'form': form})'''

'''@login_required
def amministrazione_view(request):
    return render(request, 'events/admin.html', {})'''



def is_admin(user):
    return user.is_superuser


#@user_passes_test(is_admin)
@login_required
def amministrazione_view(request):
    if not request.user.is_authenticated:
        redirect('login')
    if not request.user.is_superuser:
        return redirect('home')

    aziende = Azienda.objects.all()  # Ottieni tutte le aziende
    azienda_selezionata = None
    nome_rilievo_selezionato = None
    utente_selezionato = None
    user_profiles = []

    # Inizializza i form
    azienda_form = AziendaForm()
    user_form = UserForm()
    user_profile_form = UserProfileForm()
    form = RilieviFormOutput()
    admin_rilievo_form = AdminRilieviFormInput()
    deactivate_user_form = DeactivateUserForm()
    reactivate_user_form = ReactivateUserForm()
    reassign_rilievi_form = ReassignRilieviForm()

    form = RilieviFormOutput(request.POST, request.FILES)
    rilievo_nome = request.POST.get('rilievo_selezionato')
    superfice = request.POST.get('m2')
    dimensione = request.POST.get('dimensione')
    metri_sottoservizi = request.POST.get('metri_sottoservizi')
    t_elab = request.POST.get('t_elab')
    numero_anomalie = request.POST.get('numero_anomalie')
    
    if request.method == 'POST':
        # Ottieni il nome dell'azienda selezionata dal form
        azienda_nome = request.POST.get('azienda_selezionata')
        if azienda_nome:
            try:
                azienda_selezionata = Azienda.objects.get(nome_azienda=azienda_nome)
                # Ottieni tutti gli utenti dell'azienda selezionata
                user_profiles = UserProfile.objects.filter(azienda=azienda_selezionata)
            except Azienda.DoesNotExist:
                azienda_selezionata = None
        
        # Gestisci selezione utente
        utente_id = request.POST.get('utente_selezionato')
        if utente_id:
            try:
                utente_selezionato = int(utente_id)
            except ValueError:
                utente_selezionato = None

        # Aggiorna i form contestuali con l'azienda corrente
        deactivate_user_form = DeactivateUserForm(azienda=azienda_selezionata)
        reactivate_user_form = ReactivateUserForm(azienda=azienda_selezionata)
        reassign_rilievi_form = ReassignRilieviForm(azienda=azienda_selezionata)

        print(request.POST)
        if form.is_valid():
            print('Valido')
            try:
                # Gestione file JSON per dati automatici
                json_data = {}
                if 'json_data_file' in request.FILES:
                    json_file = request.FILES['json_data_file']
                    try:
                        json_content = json_file.read().decode('utf-8')
                        json_data = json.loads(json_content)
                        
                        # Estrai i dati dal JSON se non sono già presenti nel form
                        if not superfice and 'superficie' in json_data:
                            superfice = json_data['superficie']
                        if not dimensione and 'dimensione' in json_data:
                            dimensione = json_data['dimensione']
                        if not metri_sottoservizi and 'metri_sottoservizi' in json_data:
                            metri_sottoservizi = json_data['metri_sottoservizi']
                        if not t_elab and 'tempo_elaborazione' in json_data:
                            t_elab = json_data['tempo_elaborazione']
                        if not numero_anomalie and 'numero_anomalie' in json_data:
                            numero_anomalie = json_data['numero_anomalie']
                    except json.JSONDecodeError as e:
                        messages.error(request, f'Errore nel parsing del file JSON: {str(e)}')
                        return HttpResponseRedirect(reverse('amministrazione'))
                    except Exception as e:
                        messages.error(request, f'Errore nella lettura del file JSON: {str(e)}')
                        return HttpResponseRedirect(reverse('amministrazione'))

                # Se rilievo_selezionato è il nome del rilievo
                rilievo = Rilievi.objects.get(nome_rilievo=rilievo_nome, azienda=azienda_selezionata)

                # Validazione campi obbligatori
                missing_fields = []
                if not superfice: missing_fields.append('superficie')
                if not dimensione: missing_fields.append('dimensione')
                if not t_elab: missing_fields.append('tempo_elaborazione')
                
                # Validazione: almeno uno tra metri_sottoservizi (GPR) o numero_anomalie (MAG) deve essere presente
                if not metri_sottoservizi and not numero_anomalie:
                    messages.error(request, 'Devi compilare almeno uno dei seguenti campi: "Metri lineari sottoservizi" (per rilievi GPR) o "Numero anomalie trovate" (per rilievi Magnetometro).')
                    return HttpResponseRedirect(reverse('amministrazione'))
                
                if missing_fields:
                    messages.error(request, f'Campi mancanti: {", ".join(missing_fields)}. Assicurati di caricare un file JSON valido o compilare manualmente tutti i campi.')
                    return HttpResponseRedirect(reverse('amministrazione'))
                # In alternativa, se usi l'ID: 
                # rilievo = Rilievi.objects.get(pk=rilievo_id)

                # Prima di aggiornare, sottrai i valori precedenti dai totali azienda
                try:
                    old_m2 = float(rilievo.m2 or 0)
                    old_dim = float(rilievo.dimensione or 0)
                    old_metri = float(rilievo.metri_sottoservizi or 0)
                    old_t = float(rilievo.t_elab or 0)
                except Exception:
                    old_m2 = old_dim = old_metri = old_t = 0.0

                if azienda_selezionata:
                    try:
                        # Sottrai sempre la vecchia dimensione (sia per rilievi elaborati che non elaborati)
                        if old_dim > 0:
                            azienda_selezionata.giga_elab = float(azienda_selezionata.giga_elab or 0) - old_dim
                        
                        # Sottrai gli altri valori solo se il rilievo era già elaborato
                        if rilievo.stato == 2:
                            azienda_selezionata.tempo_tot_elab = float(azienda_selezionata.tempo_tot_elab or 0) - old_t
                            azienda_selezionata.m2_elab = float(azienda_selezionata.m2_elab or 0) - old_m2
                            # Sottrai metri_lineari_ril solo se il rilievo precedente aveva metri_sottoservizi
                            if old_metri > 0:
                                azienda_selezionata.metri_lineari_ril = float(azienda_selezionata.metri_lineari_ril or 0) - old_metri
                    except Exception:
                        pass

                # Aggiorna i campi del rilievo con i dati dal form
                rilievo.file_output = form.cleaned_data['file_output']
                rilievo.stato = 2  # Stato = Elaborato
                rilievo.created_at_output = timezone.now()
                rilievo.m2 = superfice
                rilievo.dimensione = dimensione
                # Assegna metri_sottoservizi solo se presente (per rilievi GPR)
                if metri_sottoservizi:
                    rilievo.metri_sottoservizi = float(metri_sottoservizi)
                else:
                    rilievo.metri_sottoservizi = 0.0
                rilievo.t_elab = t_elab
                # Assegna numero_anomalie solo se presente (per rilievi Magnetometro)
                if numero_anomalie:
                    rilievo.numero_anomalie = int(numero_anomalie)
                else:
                    rilievo.numero_anomalie = 0
                shapefile = form.cleaned_data['shapefile']

                if shapefile:
                    # Rinominiamo il file come "nomeRilievo.geojson"
                    shapefile.name = f"{rilievo.nome_rilievo}.geojson"
                    rilievo.shapefile = shapefile
                rilievo.save()
                rilievi = Rilievi.objects.filter(azienda=azienda_selezionata, stato=2)
                numero_rilievi = rilievi.count()
                azienda_selezionata.n_file_elab = int(numero_rilievi)
                try:
                    azienda_selezionata.giga_elab = float(azienda_selezionata.giga_elab or 0) + float(dimensione)
                except Exception:
                    azienda_selezionata.giga_elab = 0 + float(dimensione)
                try:
                    azienda_selezionata.tempo_tot_elab = float(azienda_selezionata.tempo_tot_elab or 0) + float(t_elab)
                except Exception:
                    azienda_selezionata.tempo_tot_elab = 0 + float(t_elab)
                try:
                    azienda_selezionata.m2_elab = float(azienda_selezionata.m2_elab or 0) + float(superfice)
                except Exception:
                    azienda_selezionata.m2_elab = 0 + float(superfice)
                # Aggiorna metri_lineari_ril solo se metri_sottoservizi è presente
                if metri_sottoservizi:
                    try:
                        azienda_selezionata.metri_lineari_ril = float(azienda_selezionata.metri_lineari_ril or 0) + float(metri_sottoservizi)
                    except Exception:
                        azienda_selezionata.metri_lineari_ril = 0 + float(metri_sottoservizi)

                azienda_selezionata.save()
                #invia_email(oggetto='Elaborazione finita • rilievo: ' +rilievo_nome,
                #            testo='Abbiamo finito di elaborare il rilievo ' +rilievo_nome+'.\nOra è disponibile il risultato sul portale www.deepgeo.com.',
                #            destinatari=[azienda_selezionata.mail_referente, rilievo.user])
                messages.success(request, 'Rilievo aggiornato con successo!')
                return HttpResponseRedirect(reverse('amministrazione'))
                #return HttpResponseRedirect('/amministrazione/')
            except Rilievi.DoesNotExist:
                messages.error(request, 'Rilievo selezionato non trovato.')
        else:
            messages.error(request, 'Errore nel caricamento del rilievo.')

        # Gestione dei diversi form inviati
        if 'create_azienda' in request.POST:
            # Codice per gestire la creazione di una nuova azienda
            azienda_form = AziendaForm(request.POST)
            if azienda_form.is_valid():
                azienda_form.save()
                messages.success(request, 'Azienda registrata con successo!')
                azienda_form = AziendaForm()  # Re-inizializza il form
                return HttpResponseRedirect('/amministrazione/')
            else:
                print(azienda_form.errors.as_data())
                messages.error(request, 'Errore nella registrazione dell\'azienda.')

        # Gestione creazione rilievo completo da admin
        if 'create_rilievo_completo' in request.POST:
            # Ottieni azienda dal form (dovrebbe essere quella selezionata nella pagina)
            azienda_nome = request.POST.get('admin_azienda_selezionata')
            utente_id = request.POST.get('admin_utente_selezionato')
            
            # Se non c'è azienda nel POST, prova a prenderla dalla selezione esistente nella pagina
            if not azienda_nome:
                # Cerca di ottenere l'azienda dalla selezione esistente nella pagina
                azienda_nome_from_selection = request.POST.get('azienda_selezionata')
                if azienda_nome_from_selection:
                    azienda_nome = azienda_nome_from_selection
                else:
                    messages.error(request, 'Seleziona un\'azienda dal menu sopra prima di creare un rilievo.')
                    return HttpResponseRedirect(reverse('amministrazione'))
            
            if not utente_id:
                messages.error(request, 'Seleziona un utente prima di creare un rilievo.')
                return HttpResponseRedirect(reverse('amministrazione'))
            
            try:
                azienda_selezionata = Azienda.objects.get(nome_azienda=azienda_nome)
                utente = User.objects.get(id=utente_id)
                
                # Verifica che l'utente appartenga all'azienda
                try:
                    user_profile = UserProfile.objects.get(user=utente, azienda=azienda_selezionata)
                except UserProfile.DoesNotExist:
                    messages.error(request, 'L\'utente selezionato non appartiene all\'azienda selezionata.')
                    return HttpResponseRedirect(reverse('amministrazione'))
                
                # Crea il form con i dati e passa l'azienda per la validazione
                admin_rilievo_form = AdminRilieviFormInput(
                    request.POST, 
                    request.FILES,
                    azienda_selezionata=azienda_selezionata
                )
                
                if admin_rilievo_form.is_valid():
                    rilievo = admin_rilievo_form.save(commit=False)
                    rilievo.nome_file = rilievo.file_input.name
                    rilievo.user = utente
                    rilievo.azienda = azienda_selezionata
                    
                    # Calcola la dimensione del file se non è già stata specificata e c'è un file_input
                    if rilievo.file_input and not rilievo.dimensione:
                        file_size_bytes = rilievo.file_input.size
                        file_size_gb = file_size_bytes / (1024 ** 3)  # Converti bytes in GB
                        rilievo.dimensione = file_size_gb
                    
                    # Determina lo stato in base ai dati inseriti
                    if rilievo.file_output and rilievo.m2 and rilievo.dimensione and rilievo.t_elab:
                        # Se ha file_output e tutti i dati, è già elaborato
                        rilievo.stato = 2  # Elaborato
                        rilievo.created_at_output = timezone.now()
                    elif rilievo.file_output:
                        # Se ha solo file_output, è in elaborazione
                        rilievo.stato = 1  # In Elaborazione
                    else:
                        # Se non ha file_output, è in coda
                        rilievo.stato = 0  # In Coda
                    
                    rilievo.save()
                    
                    # Se il rilievo non è elaborato e ha una dimensione, aggiorna giga_elab dell'azienda
                    # (per i rilievi elaborati, la dimensione viene gestita nella logica successiva)
                    if rilievo.stato != 2 and rilievo.dimensione and azienda_selezionata:
                        try:
                            azienda_selezionata.giga_elab = float(azienda_selezionata.giga_elab or 0) + float(rilievo.dimensione)
                            azienda_selezionata.save()
                        except Exception as e:
                            print(f"Errore nell'aggiornamento giga_elab: {e}")
                    
                    # Se il rilievo è stato creato come elaborato, aggiorna le statistiche dell'azienda
                    if rilievo.stato == 2 and azienda_selezionata:
                        # Aggiorna le statistiche dell'azienda
                        rilievi_elaborati = Rilievi.objects.filter(azienda=azienda_selezionata, stato=2)
                        azienda_selezionata.n_file_elab = rilievi_elaborati.count()
                        
                        # Aggiorna i totali
                        if rilievo.dimensione:
                            azienda_selezionata.giga_elab = float(azienda_selezionata.giga_elab or 0) + float(rilievo.dimensione)
                        if rilievo.t_elab:
                            azienda_selezionata.tempo_tot_elab = float(azienda_selezionata.tempo_tot_elab or 0) + float(rilievo.t_elab)
                        if rilievo.m2:
                            azienda_selezionata.m2_elab = float(azienda_selezionata.m2_elab or 0) + float(rilievo.m2)
                        if rilievo.metri_sottoservizi:
                            azienda_selezionata.metri_lineari_ril = float(azienda_selezionata.metri_lineari_ril or 0) + float(rilievo.metri_sottoservizi)
                        
                        azienda_selezionata.save()
                    
                    messages.success(request, f'Rilievo "{rilievo.nome_rilievo}" creato con successo per l\'utente {utente.first_name} {utente.last_name}!')
                    
                    # Aggiorna azienda_selezionata per mostrare il nuovo rilievo
                    azienda_selezionata = Azienda.objects.get(nome_azienda=azienda_nome)
                    
                    # Re-inizializza il form per pulire i campi
                    admin_rilievo_form = AdminRilieviFormInput()
                    
                    return HttpResponseRedirect(reverse('amministrazione'))
                else:
                    messages.error(request, f'Errore nella creazione del rilievo: {admin_rilievo_form.errors}')
            except Azienda.DoesNotExist:
                messages.error(request, 'Azienda non trovata.')
            except User.DoesNotExist:
                messages.error(request, 'Utente non trovato.')
            except Exception as e:
                messages.error(request, f'Errore durante la creazione del rilievo: {str(e)}')

        if 'deactivate_user' in request.POST:
            deactivate_user_form = DeactivateUserForm(request.POST, azienda=azienda_selezionata)
            if deactivate_user_form.is_valid():
                user_to_deactivate = deactivate_user_form.cleaned_data['utente']

                if user_to_deactivate.is_superuser:
                    messages.error(request, 'Non puoi disattivare un amministratore dal portale.')
                else:
                    user_to_deactivate.is_active = False
                    user_to_deactivate.save()
                    messages.success(
                        request,
                        f'Utente "{user_to_deactivate.get_full_name() or user_to_deactivate.username}" disattivato con successo.'
                    )
                    return HttpResponseRedirect(reverse('amministrazione'))
            else:
                messages.error(request, 'Seleziona un utente valido da disattivare.')

        if 'reactivate_user' in request.POST:
            reactivate_user_form = ReactivateUserForm(request.POST, azienda=azienda_selezionata)
            if reactivate_user_form.is_valid():
                user_to_reactivate = reactivate_user_form.cleaned_data['utente']

                if user_to_reactivate.is_superuser:
                    messages.error(request, 'Gli account amministratore non dovrebbero risultare disattivati.')
                else:
                    user_to_reactivate.is_active = True
                    user_to_reactivate.save()
                    messages.success(
                        request,
                        f'Utente "{user_to_reactivate.get_full_name() or user_to_reactivate.username}" riattivato con successo.'
                    )
                    return HttpResponseRedirect(reverse('amministrazione'))
            else:
                messages.error(request, 'Seleziona un utente valido da riattivare.')

        if 'reassign_rilievi' in request.POST:
            reassign_rilievi_form = ReassignRilieviForm(request.POST, azienda=azienda_selezionata)
            if reassign_rilievi_form.is_valid():
                user_sorgente = reassign_rilievi_form.cleaned_data['user_sorgente']
                user_destinazione = reassign_rilievi_form.cleaned_data['user_destinazione']

                try:
                    with transaction.atomic():
                        rilievi_qs = Rilievi.objects.filter(user=user_sorgente, azienda=azienda_selezionata)
                        moved_count = rilievi_qs.update(user=user_destinazione)

                    if moved_count == 0:
                        messages.warning(
                            request,
                            f'Nessun rilievo da spostare per l\'utente {user_sorgente.get_full_name() or user_sorgente.username}.'
                        )
                    else:
                        messages.success(
                            request,
                            f'{moved_count} rilievi riassegnati da {user_sorgente.get_full_name() or user_sorgente.username} '
                            f'a {user_destinazione.get_full_name() or user_destinazione.username}.'
                        )
                    return HttpResponseRedirect(reverse('amministrazione'))
                except Exception as e:
                    messages.error(request, f'Errore durante la riassegnazione dei rilievi: {e}')
            else:
                messages.error(request, 'Compila correttamente il form di riassegnazione.')

        if 'create_user' in request.POST:
            user_form = UserForm(request.POST)
            user_profile_form = UserProfileForm(request.POST)
            print(user_form.is_valid())
            print(user_profile_form.is_valid())
            if user_form.is_valid() and user_profile_form.is_valid():
                username = user_form.cleaned_data['username']
                email = user_form.cleaned_data['email']
                if User.objects.filter(username=username).exists():
                    messages.error(request, 'Un utente con questo username esiste già.')
                elif User.objects.filter(email=email).exists():
                    messages.error(request, 'Un utente con questa email esiste già.')
                else:
                    try:
                        new_user = User.objects.create_user(
                            username = user_form.cleaned_data['email'],
                            email = user_form.cleaned_data['email'],
                            first_name = user_form.cleaned_data['first_name'],
                            last_name = user_form.cleaned_data['last_name'],
                            password = user_form.cleaned_data['password'],
                        )
                        new_user.save()
                        print('user saved')
                        print('#########################', email)
                        # Recupera l'azienda associata dal form
                        azienda_user = Azienda.objects.get(nome_azienda=user_profile_form.cleaned_data['azienda'].nome_azienda)

                        # Recupera l'utente associato dal form
                        user_user = User.objects.get(username=email)

                        # Cerca se esiste già un UserProfile per questo utente
                        user_profile, created = UserProfile.objects.get_or_create(
                            user=user_user,
                            defaults={'azienda': azienda_user}  # Se il profilo non esiste, viene creato con questo valore predefinito
                        )

                        # Se il profilo esiste già, puoi aggiornare l'azienda associata
                        if not created:
                            user_profile.azienda = azienda_user
                            user_profile.save()
                        print('user profile salvato')
                        return HttpResponseRedirect('/amministrazione/')
                        #print(new.user)
                        '''new.save()
                        user = user_form.save(commit=False)
                        user.set_password(user_form.cleaned_data['password'])  # Cripta la password
                        user.save()'''

                        '''user_profile = user_profile_form.save(commit=False)
                        user_profile.user = user
                        user_profile.azienda = user_profile_form.cleaned_data['azienda']
                        print('################################', type(user_profile.azienda))
                        user_profile.save()'''

                        
                        '''messages.success(request, 'Utente registrato con successo!')
                        user_form = UserForm()
                        user_profile_form = UserProfileForm()'''
                    except Exception as e:
                        print(e)
                        messages.error(request, f'Errore durante la creazione dell\'utente: {e}')
            else:
                messages.error(request, 'Errore nella registrazione dell\'utente.')

        '''if 'upload_file' in request.POST:
            # Codice per gestire il caricamento dei file
            form = RilieviElaboratiForm(request.POST, request.FILES)
            print(azienda_selezionata)
            print(form.is_valid())
            if form.is_valid():
                rilievo = form.save(commit=False)
                rilievo.nome_file = rilievo.file.name
                rilievo.user = request.user
                rilievo.azienda = azienda_selezionata
                rilievo.save()
                messages.success(request, 'Rilievo caricato con successo!')
                form = RilieviElaboratiForm()
            else:
                messages.error(request, 'Errore nel caricamento del rilievo.')'''

    else:
        # Richiesta GET: aggiorna i form con l'azienda selezionata (se presente)
        deactivate_user_form = DeactivateUserForm(azienda=azienda_selezionata)
        reactivate_user_form = ReactivateUserForm(azienda=azienda_selezionata)
        reassign_rilievi_form = ReassignRilieviForm(azienda=azienda_selezionata)

    if request.method == 'POST' and 'deactivate_user' not in request.POST:
        deactivate_user_form = DeactivateUserForm(azienda=azienda_selezionata)
    if request.method == 'POST' and 'reactivate_user' not in request.POST:
        reactivate_user_form = ReactivateUserForm(azienda=azienda_selezionata)
    if request.method == 'POST' and 'reassign_rilievi' not in request.POST:
        reassign_rilievi_form = ReassignRilieviForm(azienda=azienda_selezionata)

    # Recupera i rilievi per l'azienda selezionata
    rilievi_list = Rilievi.objects.filter(azienda=azienda_selezionata).order_by('-created_at_input') if azienda_selezionata else []
    
    # Filtra per utente se selezionato
    if utente_selezionato and rilievi_list:
        rilievi_list = rilievi_list.filter(user_id=utente_selezionato)
    
    # Ottieni gli utenti dell'azienda selezionata per il dropdown
    if azienda_selezionata:
        user_profiles = UserProfile.objects.filter(azienda=azienda_selezionata)
    else:
        user_profiles = []
    
    # Ottieni tutti gli utenti organizzati per azienda per il form admin rilievo
    # Crea una lista di tuple (azienda, lista_utenti) per il template
    all_user_profiles_by_azienda_list = []
    for azienda in aziende:
        user_profiles_list = list(UserProfile.objects.filter(azienda=azienda).select_related('user'))
        all_user_profiles_by_azienda_list.append((azienda, user_profiles_list))
    
    # Ottieni tutti i nomi dei rilievi organizzati per azienda per la validazione JavaScript
    # Crea una lista di tuple (nome_azienda, lista_nomi_rilievi) per il template
    all_rilievi_names_by_azienda_list = []
    for azienda in aziende:
        rilievi_names = list(Rilievi.objects.filter(azienda=azienda).values_list('nome_rilievo', flat=True))
        all_rilievi_names_by_azienda_list.append((azienda.nome_azienda, rilievi_names))

    #rilievi_elaborati_list = RilieviElaborati.objects.filter(azienda=azienda_selezionata).order_by('-created_at') if azienda_selezionata else []

    return render(request, 'events/admin_new.html', {
        'azienda_form': azienda_form,
        'user_form': user_form,
        'user_profile_form': user_profile_form,
        'deactivate_user_form': deactivate_user_form,
        'reactivate_user_form': reactivate_user_form,
        'reassign_rilievi_form': reassign_rilievi_form,
        'rilievi_list': rilievi_list,
        #'rilievi_elaborati_list': rilievi_elaborati_list,
        'aziende': aziende,
        'azienda_selezionata': azienda_selezionata,
        'utente_selezionato': utente_selezionato,
        'user_profiles': user_profiles,
        'all_user_profiles_by_azienda_list': all_user_profiles_by_azienda_list,
        'all_rilievi_names_by_azienda_list': all_rilievi_names_by_azienda_list,
        'form': form,
        'admin_rilievo_form': admin_rilievo_form,
    })

import os
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.http import JsonResponse

@login_required
def elimina_rilievo(request, rilievo_id):
    if not request.user.is_superuser:
        rilievo = get_object_or_404(Rilievi, id=rilievo_id, user=request.user)
    elif request.user.is_superuser:
        rilievo = get_object_or_404(Rilievi, id=rilievo_id)

    if request.method == 'POST':
        # Cancella il file fisico dalla cartella media
        if rilievo.file_input:
            file_path = rilievo.file_input.path

            '''geojson_file = rilievo.shapefile.path'''
            if os.path.exists(file_path):
                os.remove(file_path)
            if rilievo.shapefile:
                os.remove(rilievo.shapefile.path)

        # Prima di eliminare, aggiorna i totali dell'azienda sottraendo i valori del rilievo
        if rilievo.azienda is not None:
            azienda = rilievo.azienda
            try:
                # Sottrai sempre la dimensione del file caricato (sia per rilievi elaborati che non elaborati)
                if rilievo.dimensione:
                    azienda.giga_elab = float(azienda.giga_elab or 0) - float(rilievo.dimensione or 0)
                
                # Sottrai gli altri valori solo se il rilievo è elaborato
                if rilievo.stato == 2:
                    azienda.tempo_tot_elab = float(azienda.tempo_tot_elab or 0) - float(rilievo.t_elab or 0)
                    azienda.m2_elab = float(azienda.m2_elab or 0) - float(rilievo.m2 or 0)
                    azienda.metri_lineari_ril = float(azienda.metri_lineari_ril or 0) - float(rilievo.metri_sottoservizi or 0)
                azienda.save()
            except Exception:
                pass

        # Elimina l'oggetto dal database
        azienda_ref = rilievo.azienda
        rilievo.delete()

        # Se esiste un'azienda, aggiorna n_file_elab ricalcolando
        if azienda_ref is not None:
            try:
                n_elab = Rilievi.objects.filter(azienda=azienda_ref, stato=2).count()
                azienda_ref.n_file_elab = int(n_elab)
                azienda_ref.save()
            except Exception:
                pass
        return JsonResponse({'success': True})
    return JsonResponse({'success': False}, status=400)

@login_required
def elimina_rilievo_elaborato(request, rilievo_id):
    rilievo = get_object_or_404(Rilievi, id=rilievo_id, user=request.user)
    if request.method == 'POST':
        # Cancella il file fisico dalla cartella media
        if rilievo.file:
            file_path = rilievo.file.path
            if os.path.exists(file_path):
                os.remove(file_path)
        
        # Elimina l'oggetto dal database
        rilievo.delete()
        return JsonResponse({'success': True})
    return JsonResponse({'success': False}, status=400)

'''@receiver(post_save, sender=Azienda)
def crea_cartella_azienda(sender, instance, created, **kwargs):
    if created:  # Controlla se è stato creato un nuovo record
        # Definisci il percorso della nuova cartella
        base_path = os.path.join(settings.MEDIA_ROOT)
        cartella_azienda = os.path.join(base_path, f"{instance.nome_azienda}")
        # Crea la cartella se non esiste
        os.makedirs(cartella_azienda, exist_ok=True)
        inputdir = os.path.join(cartella_azienda,'input')
        outputdir = os.path.join(cartella_azienda,'output')
        os.makedirs(inputdir, exist_ok=True)
        os.makedirs(outputdir, exist_ok=True)'''

import os
import json
from django.conf import settings
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from .models import Rilievi


@login_required
def map(request):
    aziende = None
    selected_company_name = request.GET.get('azienda')

    # Determina l'azienda di riferimento
    if request.user.is_superuser:
        aziende = Azienda.objects.all().order_by('nome_azienda')
        if selected_company_name:
            try:
                azienda = Azienda.objects.get(nome_azienda=selected_company_name)
            except Azienda.DoesNotExist:
                azienda = None
        else:
            azienda = None
    else:
        try:
            user_profile = request.user.userprofile
            azienda = user_profile.azienda
        except UserProfile.DoesNotExist:
            azienda = None

    # Filtra i rilievi in base al tipo di utente
    if request.user.is_superuser:
        rilievi_elaborati = Rilievi.objects.filter(azienda=azienda, stato=2) if azienda else []
    else:
        if azienda and azienda.privacy_mode:
            rilievi_elaborati = Rilievi.objects.filter(user=request.user, azienda=azienda, stato=2)
        else:
            rilievi_elaborati = Rilievi.objects.filter(azienda=azienda, stato=2) if azienda else []

    rilievi_data = []
    for r in rilievi_elaborati:
        shapefile_field = getattr(r, 'shapefile', None)
        if not shapefile_field:
            print(f"Nessun file GeoJSON associato al rilievo {r.id} - {r.nome_rilievo}")
            continue

        try:
            shapefile_path = Path(shapefile_field.path)
        except (ValueError, FileNotFoundError) as exc:
            print(f"Percorso GeoJSON non valido per il rilievo {r.id} - {r.nome_rilievo}: {exc}")
            continue

        if not shapefile_path.is_file():
            print(f"File GeoJSON non trovato per il rilievo {r.id} - {r.nome_rilievo}: {shapefile_path}")
            continue

        try:
            with shapefile_path.open('r', encoding='utf-8') as f:
                data = json.load(f)
        except (OSError, json.JSONDecodeError) as exc:
            print(f"Impossibile leggere il GeoJSON per il rilievo {r.id} - {r.nome_rilievo}: {exc}")
            continue

        rilievi_data.append({
            'id': r.id,
            'nome': r.nome_rilievo,
            'latitudine': r.latitudine,
            'longitudine': r.longitudine,
            'superfice_rilievo': r.m2,
            'metri_lineari_sottoservizi_trovati': r.metri_sottoservizi,
            'geojson_text': data,
        })

    print('rilievi_elaborati1')
    rilievi_json = json.dumps(rilievi_data)

    # Gestisci rilievo selezionato
    rilievo_id = request.GET.get('rilievo_id', None)
    try:
        selected_rilievo_id = int(rilievo_id) if rilievo_id else None
    except ValueError:
        selected_rilievo_id = None

    return render(request, 'events/map_new.html', {
        'rilievi_elaborati_json': rilievi_json,
        'selected_rilievo_id': selected_rilievo_id,
        'aziende': aziende,
        'azienda_selezionata': azienda.nome_azienda if azienda else '',
    })


@login_required
def stats(request):
    # Ottieni l'azienda dell'utente loggato direttamente dall'oggetto UserProfile
    user_profile = request.user.userprofile
    azienda = user_profile.azienda
    
    if not azienda:
        messages.error(request, 'Nessuna azienda associata al tuo profilo.')
        return redirect('home')
     
    # Filtra i rilievi per tipo GPR e MAG (solo quelli elaborati, stato=2)
    # Include anche i rilievi con survey_type vuoto/null come GPR (default del modello)
    from django.db.models import Q
    rilievi_gpr_elab = Rilievi.objects.filter(
        azienda=azienda, 
        stato=2
    ).filter(Q(survey_type='GPR') | Q(survey_type='') | Q(survey_type__isnull=True))
    
    rilievi_mag_elab = Rilievi.objects.filter(azienda=azienda, survey_type='MAG', stato=2)
    
    # Conta il totale dei rilievi (tutti gli stati) per GPR e MAG dal database
    # Include anche i rilievi con survey_type vuoto/null come GPR
    n_file_tot_gpr = Rilievi.objects.filter(azienda=azienda).filter(
        Q(survey_type='GPR') | Q(survey_type='') | Q(survey_type__isnull=True)
    ).count()
    n_file_tot_mag = Rilievi.objects.filter(azienda=azienda, survey_type='MAG').count()
    
    # Debug: verifica se ci sono rilievi con survey_type null o vuoto
    # total_rilievi_azienda = Rilievi.objects.filter(azienda=azienda).count()
    # print(f"Totale rilievi azienda: {total_rilievi_azienda}")
    # print(f"Totale GPR: {n_file_tot_gpr}, Totale MAG: {n_file_tot_mag}")
    
    # Conta i rilievi elaborati direttamente dal database (stato=2)
    n_file_elab_gpr = rilievi_gpr_elab.count()
    n_file_elab_mag = rilievi_mag_elab.count()
    
    # Debug: verifica i conteggi
    # print(f"Elaborati GPR: {n_file_elab_gpr}, Elaborati MAG: {n_file_elab_mag}")
    
    # Calcola statistiche GPR dal database
    giga_elab_gpr = sum(float(r.dimensione or 0) for r in rilievi_gpr_elab)
    m2_elab_gpr = sum(float(r.m2 or 0) for r in rilievi_gpr_elab)
    tempo_tot_elab_gpr = sum(float(r.t_elab or 0) for r in rilievi_gpr_elab)
    metri_lineari_ril_gpr = sum(float(r.metri_sottoservizi or 0) for r in rilievi_gpr_elab)
    tempo_elab_medio_gpr = (tempo_tot_elab_gpr / m2_elab_gpr) if m2_elab_gpr > 0 else 0.00
    
    # Calcola GB caricati totali per GPR (tutti i rilievi, non solo elaborati)
    rilievi_gpr_tot = Rilievi.objects.filter(azienda=azienda).filter(
        Q(survey_type='GPR') | Q(survey_type='') | Q(survey_type__isnull=True)
    )
    giga_caricati_gpr = sum(float(r.dimensione or 0) for r in rilievi_gpr_tot)
    
    # Calcola statistiche MAG dal database
    giga_elab_mag = sum(float(r.dimensione or 0) for r in rilievi_mag_elab)
    m2_elab_mag = sum(float(r.m2 or 0) for r in rilievi_mag_elab)
    tempo_tot_elab_mag = sum(float(r.t_elab or 0) for r in rilievi_mag_elab)
    metri_lineari_ril_mag = sum(float(r.metri_sottoservizi or 0) for r in rilievi_mag_elab)
    tempo_elab_medio_mag = (tempo_tot_elab_mag / m2_elab_mag) if m2_elab_mag > 0 else 0.00
    # Numero anomalie trovate (somma delle anomalie di tutti i rilievi MAG elaborati)
    numero_anomalie_mag = sum(int(r.numero_anomalie or 0) for r in rilievi_mag_elab)
    
    # Calcola GB caricati totali per MAG (tutti i rilievi, non solo elaborati)
    rilievi_mag_tot = Rilievi.objects.filter(azienda=azienda, survey_type='MAG')
    giga_caricati_mag = sum(float(r.dimensione or 0) for r in rilievi_mag_tot)

    return render(request, 'events/stats2_new.html', {
        # Statistiche GPR
        'n_file_elab_gpr': n_file_elab_gpr,
        'n_file_tot_gpr': n_file_tot_gpr,
        'giga_elab_gpr': giga_elab_gpr,
        'giga_caricati_gpr': giga_caricati_gpr,
        'm2_elab_gpr': m2_elab_gpr,
        'tempo_tot_elab_gpr': tempo_tot_elab_gpr,
        'tempo_elab_medio_gpr': tempo_elab_medio_gpr,
        'metri_lineari_ril_gpr': metri_lineari_ril_gpr,
        # Statistiche MAG
        'n_file_elab_mag': n_file_elab_mag,
        'n_file_tot_mag': n_file_tot_mag,
        'giga_elab_mag': giga_elab_mag,
        'giga_caricati_mag': giga_caricati_mag,
        'm2_elab_mag': m2_elab_mag,
        'tempo_tot_elab_mag': tempo_tot_elab_mag,
        'tempo_elab_medio_mag': tempo_elab_medio_mag,
        'metri_lineari_ril_mag': metri_lineari_ril_mag,
        'numero_anomalie_mag': numero_anomalie_mag,
    })

from django.views.decorators.csrf import csrf_exempt

@login_required
@csrf_exempt
def aggiorna_stato_rilievo(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        rilievo_id = data.get('rilievo_id')
        nuovo_stato = data.get('stato')

        try:
            rilievo = Rilievi.objects.get(pk=rilievo_id)
            vecchio_stato = rilievo.stato
            nuovo_stato_int = int(nuovo_stato)
            
            # Gestisci l'aggiornamento di giga_elab e altri campi dell'azienda in base al cambio di stato
            if rilievo.azienda:
                azienda = rilievo.azienda
                
                # Se il rilievo era elaborato e ora non lo è più, sottrai i valori
                if vecchio_stato == 2 and nuovo_stato_int != 2:
                    try:
                        # Sottrai la dimensione da giga_elab
                        if rilievo.dimensione:
                            azienda.giga_elab = float(azienda.giga_elab or 0) - float(rilievo.dimensione)
                        # Sottrai gli altri valori
                        if rilievo.t_elab:
                            azienda.tempo_tot_elab = float(azienda.tempo_tot_elab or 0) - float(rilievo.t_elab)
                        if rilievo.m2:
                            azienda.m2_elab = float(azienda.m2_elab or 0) - float(rilievo.m2)
                        if rilievo.metri_sottoservizi:
                            azienda.metri_lineari_ril = float(azienda.metri_lineari_ril or 0) - float(rilievo.metri_sottoservizi)
                        azienda.save()
                    except Exception as e:
                        print(f"Errore nella sottrazione valori azienda: {e}")
                
                # Se il rilievo non era elaborato e ora lo diventa, aggiungi i valori
                elif vecchio_stato != 2 and nuovo_stato_int == 2:
                    try:
                        # Aggiungi la dimensione a giga_elab
                        if rilievo.dimensione:
                            azienda.giga_elab = float(azienda.giga_elab or 0) + float(rilievo.dimensione)
                        # Aggiungi gli altri valori
                        if rilievo.t_elab:
                            azienda.tempo_tot_elab = float(azienda.tempo_tot_elab or 0) + float(rilievo.t_elab)
                        if rilievo.m2:
                            azienda.m2_elab = float(azienda.m2_elab or 0) + float(rilievo.m2)
                        if rilievo.metri_sottoservizi:
                            azienda.metri_lineari_ril = float(azienda.metri_lineari_ril or 0) + float(rilievo.metri_sottoservizi)
                        azienda.save()
                    except Exception as e:
                        print(f"Errore nell'aggiunta valori azienda: {e}")
            
            # Aggiorna lo stato del rilievo
            rilievo.stato = nuovo_stato_int
            
            # Aggiorna created_at_output se lo stato diventa "Elaborato"
            if nuovo_stato_int == 2 and not rilievo.created_at_output:
                rilievo.created_at_output = timezone.now()
            
            # Invia email in base al nuovo stato
            if nuovo_stato == '1':
                invia_email(oggetto='Elaborazione iniziata • Rilievo: ' + rilievo.nome_rilievo,
                            testo='Il rilievo ' + rilievo.nome_rilievo + ' è in fase di elaborazione.\n',
                            destinatari=[Azienda.objects.get(nome_azienda=rilievo.azienda).mail_referente, rilievo.user])
            elif nuovo_stato == '2':
                invia_email(oggetto='Elaborazione finita • rilievo: ' + rilievo.nome_rilievo,
                            testo='Abbiamo finito di elaborare il rilievo ' + rilievo.nome_rilievo + '.\nOra è disponibile il risultato sul portale www.deepgeo.com.',
                            destinatari=[Azienda.objects.get(nome_azienda=rilievo.azienda).mail_referente, rilievo.user])
            elif nuovo_stato == '3':
                invia_email(oggetto="Errore durante l'elaborazione • Rilievo: " + rilievo.nome_rilievo,
                            testo="L'elaborazione del rilievo "+ rilievo.nome_rilievo +" non è andato a buon fine.\n Si prega di contattare l'assistenza all'indirizzo technicalsupport@xploragroup.ai per risolvere il problema.",
                            destinatari=[Azienda.objects.get(nome_azienda=rilievo.azienda).mail_referente, rilievo.user])
            rilievo.save()
            
            # Aggiorna n_file_elab dopo il salvataggio per avere il conteggio corretto
            if rilievo.azienda:
                try:
                    rilievi_elaborati = Rilievi.objects.filter(azienda=rilievo.azienda, stato=2).count()
                    rilievo.azienda.n_file_elab = rilievi_elaborati
                    rilievo.azienda.save()
                except Exception as e:
                    print(f"Errore nell'aggiornamento n_file_elab: {e}")
            
            return JsonResponse({'success': True})
        except Rilievi.DoesNotExist and Exception as e:
            print(e)
            # Invia notifica errore
            invia_notifica_errore(request, e, "404")
            return JsonResponse({'success': False, 'error': 'Rilievo non trovato'})

    return JsonResponse({'success': False, 'error': 'Metodo non supportato'}, status=400)

@login_required
@csrf_exempt
def aggiorna_priorita_rilievo(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        rilievo_id = data.get('rilievo_id')
        nuova_priorita = data.get('priorita')

        try:
            rilievo = Rilievi.objects.get(pk=rilievo_id)
            rilievo.priorita = int(nuova_priorita)
            rilievo.save()
            return JsonResponse({'success': True})
        except Rilievi.DoesNotExist:
            # Invia notifica errore
            invia_notifica_errore(request, "Rilievo non trovato per eliminazione", "404")
            return JsonResponse({'success': False, 'error': 'Rilievo non trovato'})

    return JsonResponse({'success': False, 'error': 'Metodo non supportato'}, status=400)


from django.core.mail import send_mail
from django.conf import settings
from django.http import HttpResponseRedirect
from django.urls import reverse


def invia_email(oggetto,testo,destinatari=[]):
    subject = oggetto
    message = testo
    from_email = 'deepgeo@xploragroup.ai'
    recipient_list = destinatari

    #send_mail(subject, message, from_email, recipient_list)


def invia_notifica_errore(request, errore, codice_errore="500", traceback_info=None):
    """Invia notifica email per errori del server a technicalsupport@xploragroup.ai"""
    from datetime import datetime
    import traceback as tb
    
    # Ottieni informazioni sull'utente
    utente_info = "Utente non autenticato"
    if request.user.is_authenticated:
        utente_info = f"{request.user.first_name} {request.user.last_name} ({request.user.email})"
        if hasattr(request.user, 'userprofile') and request.user.userprofile.azienda:
            utente_info += f" - Azienda: {request.user.userprofile.azienda.nome_azienda}"
    
    # Ottieni informazioni sulla richiesta
    url_errore = request.build_absolute_uri()
    metodo_richiesta = request.method
    user_agent = request.META.get('HTTP_USER_AGENT', 'Non disponibile')
    ip_address = request.META.get('REMOTE_ADDR', 'Non disponibile')
    
    # Data e ora attuali
    now = datetime.now()
    data_ora = now.strftime('%d/%m/%Y %H:%M')
    
    # Ottieni informazioni dettagliate sull'errore (file e riga)
    errore_dettagli = str(errore)
    file_errore = "Non disponibile"
    riga_errore = "Non disponibile"
    traceback_completo = "Non disponibile"
    
    try:
        if traceback_info:
            # Usa il traceback fornito dal middleware
            traceback_completo = traceback_info
        else:
            # Genera il traceback corrente
            traceback_completo = tb.format_exc()
        
        # Estrai informazioni dal traceback
        tb_lines = traceback_completo.split('\n')
        for line in tb_lines:
            if 'File "' in line and 'line ' in line:
                # Estrai nome file e numero riga
                parts = line.split('File "')
                if len(parts) > 1:
                    file_part = parts[1].split('", line ')
                    if len(file_part) > 1:
                        file_errore = file_part[0].split('/')[-1]  # Solo il nome del file
                        riga_errore = file_part[1].split(',')[0]  # Solo il numero di riga
                        break
        
    except Exception as e:
        print(f"Errore nell'estrazione delle informazioni del traceback: {e}")
    
    # Crea oggetto e corpo dell'email
    oggetto = f"[Error {codice_errore}] {data_ora}"
    
    testo = f"""ERRORE DEL SERVER RILEVATO

UTENTE:
{utente_info}

DETTAGLI ERRORE:
URL: {url_errore}
Metodo: {metodo_richiesta}
IP: {ip_address}
User Agent: {user_agent}
Data/Ora: {data_ora}

LOCALIZZAZIONE ERRORE:
File: {file_errore}
Riga: {riga_errore}

ERRORE:
{errore_dettagli}

TRACEBACK COMPLETO:
{traceback_completo}

---
Questo è un messaggio automatico generato dal sistema DeepGeo.
"""
    print(testo)
    # Invia email a technicalsupport@xploragroup.ai
    try:
        print(f"🔔 INVIO NOTIFICA ERRORE: {oggetto}")
        #invia_email(oggetto=oggetto, testo=testo, destinatari=['technicalsupport@xploragroup.ai'])
        print("✅ Email inviata con successo!")
    except Exception as e:
        # Se anche l'invio dell'email fallisce, logga l'errore
        print(f"❌ Errore nell'invio della notifica email: {e}")


def test_error_notification(request):
    """Vista di test per la notifica errori - DA RIMUOVERE IN PRODUZIONE"""
    if not request.user.is_superuser:
        return HttpResponseRedirect('/home/')
    
    # Test 1: Errore simulato con informazioni dettagliate
    try:
        # Simula un errore per generare un traceback
        raise ValueError("Test error notification - Division by zero")
    except Exception as errore_test:
        # Genera il traceback per il test
        import traceback
        traceback_info = traceback.format_exc()
        invia_notifica_errore(request, errore_test, "TEST", traceback_info)
    
    return HttpResponse("Email di test inviata con informazioni dettagliate! Controlla technicalsupport@xploragroup.ai")


def get_system_metrics():
    """Raccoglie le metriche di sistema"""
    try:
        import psutil
        import platform
        
        # CPU
        cpu_percent = psutil.cpu_percent(interval=1)
        cpu_count = psutil.cpu_count()
        cpu_freq = psutil.cpu_freq()
        print('cpu_count')
        print(cpu_count)
        # Memoria RAM
        memory = psutil.virtual_memory()
        memory_total_gb = round(memory.total / (1024**3), 2)
        memory_used_gb = round(memory.used / (1024**3), 2)
        memory_percent = memory.percent
        
        # Disco - Gestione Windows/Linux
        import os
        if os.name == 'nt':  # Windows
            disk = psutil.disk_usage('C:\\')
        else:  # Linux/Mac
            disk = psutil.disk_usage('/')
        
        disk_total_gb = round(disk.total / (1024**3), 2)
        disk_used_gb = round(disk.used / (1024**3), 2)
        disk_free_gb = round(disk.free / (1024**3), 2)
        disk_percent = round((disk.used / disk.total) * 100, 2)
        
        # Rete
        network = psutil.net_io_counters()
        network_sent_mb = round(network.bytes_sent / (1024**2), 2)
        network_recv_mb = round(network.bytes_recv / (1024**2), 2)
        
        # Processi
        processes = len(psutil.pids())
        
        # Sistema
        boot_time = psutil.boot_time()
        uptime_seconds = psutil.time.time() - boot_time
        uptime_hours = round(uptime_seconds / 3600, 2)
        
        return {
            'cpu_percent': cpu_percent,
            'cpu_count': cpu_count,
            'cpu_freq': cpu_freq.current if cpu_freq else 0,
            'memory_total_gb': memory_total_gb,
            'memory_used_gb': memory_used_gb,
            'memory_percent': memory_percent,
            'disk_total_gb': disk_total_gb,
            'disk_used_gb': disk_used_gb,
            'disk_free_gb': disk_free_gb,
            'disk_percent': disk_percent,
            'network_sent_mb': network_sent_mb,
            'network_recv_mb': network_recv_mb,
            'processes': processes,
            'uptime_hours': uptime_hours,
            'platform': platform.system(),
            'platform_version': platform.version(),
        }
    except Exception as e:
        # Fallback se psutil non è disponibile
        print(f'Errore nel monitoraggio: {str(e)}')
        return {
            'cpu_percent': 0,
            'cpu_count': 0,
            'cpu_freq': 0,
            'memory_total_gb': 0,
            'memory_used_gb': 0,
            'memory_percent': 0,
            'disk_total_gb': 0,
            'disk_used_gb': 0,
            'disk_free_gb': 0,
            'disk_percent': 0,
            'network_sent_mb': 0,
            'network_recv_mb': 0,
            'processes': 0,
            'uptime_hours': 0,
            'platform': 'Unknown',
            'platform_version': 'Unknown',
            'error': 'psutil non installato'
        }
    except Exception as e:
        return {
            'error': f'Errore nel monitoraggio: {str(e)}'
        }


@login_required
def admin_dashboard(request):
    """Pannello di controllo per monitorare l'utilizzo delle risorse di sistema - Solo per admin"""
    if not request.user.is_authenticated:
        return redirect('login')
    if not request.user.is_superuser:
        return redirect('home')

    # Ottieni le metriche di sistema
    system_metrics = get_system_metrics()
    
    # Statistiche applicazione (manteniamo alcune per contesto)
    from django.db.models import Sum, Count
    from django.utils import timezone
    from datetime import timedelta

    total_aziende = Azienda.objects.count()
    total_users = User.objects.filter(is_superuser=False).count()
    total_rilievi = Rilievi.objects.count()
    total_rilievi_elaborati = Rilievi.objects.filter(stato=2).count()
    
    # Statistiche per periodo (ultimi 30 giorni)
    thirty_days_ago = timezone.now() - timedelta(days=30)
    rilievi_ultimi_30_giorni = Rilievi.objects.filter(created_at_input__gte=thirty_days_ago).count()
    accessi_ultimi_30_giorni = AccessLog.objects.filter(login_time__gte=thirty_days_ago).count()
    
    # Statistiche per stato rilievi
    rilievi_per_stato = list(Rilievi.objects.values('stato').annotate(count=Count('stato')))
    
    # Se non ci sono rilievi, crea una lista vuota per evitare errori JavaScript
    if not rilievi_per_stato:
        rilievi_per_stato = []
    
    stati_labels = {
        0: 'In Coda',
        1: 'In Elaborazione', 
        2: 'Elaborato',
        3: 'Errore'
    }
    
    context = {
        # Metriche di sistema
        'system_metrics': system_metrics,
        
        # Statistiche applicazione
        'total_aziende': total_aziende,
        'total_users': total_users,
        'total_rilievi': total_rilievi,
        'total_rilievi_elaborati': total_rilievi_elaborati,
        'rilievi_ultimi_30_giorni': rilievi_ultimi_30_giorni,
        'accessi_ultimi_30_giorni': accessi_ultimi_30_giorni,
        
        # Statistiche rilievi
        'rilievi_per_stato': rilievi_per_stato,
        'stati_labels': stati_labels,
    }
    
    return render(request, 'events/admin_dashboard.html', context)


@login_required
def calcola_dimensioni_rilievi(request):
    """
    Funzione per calcolare e salvare le dimensioni dei file per tutti i rilievi nel database.
    Aggiorna anche il campo giga_elab delle aziende.
    """
    if not request.user.is_superuser:
        messages.error(request, 'Accesso negato. Solo gli amministratori possono eseguire questa operazione.')
        return redirect('admin_dashboard')
    
    if request.method != 'POST':
        messages.error(request, 'Metodo non consentito.')
        return redirect('admin_dashboard')
    
    try:
        # Ottieni tutti i rilievi
        rilievi = Rilievi.objects.all()
        totale_rilievi = rilievi.count()
        rilievi_aggiornati = 0
        rilievi_senza_file = 0
        rilievi_senza_dimensione = 0
        errori = 0
        
        # Dizionario per tracciare le differenze di dimensione per azienda (per aggiornare giga_elab)
        aziende_dimensioni = {}
        
        for rilievo in rilievi:
            try:
                # Controlla se il rilievo ha un file_input
                if rilievo.file_input and rilievo.file_input.name:
                    # Calcola la dimensione del file in GB
                    try:
                        file_size_bytes = rilievo.file_input.size
                        file_size_gb = file_size_bytes / (1024 ** 3)  # Converti bytes in GB
                        
                        # Salva la vecchia dimensione per calcolare la differenza
                        old_dim = float(rilievo.dimensione or 0)
                        
                        # Salva la nuova dimensione nel rilievo
                        rilievo.dimensione = file_size_gb
                        rilievo.save()
                        
                        # Traccia la differenza per aggiornare giga_elab dell'azienda
                        if rilievo.azienda:
                            azienda_id = rilievo.azienda.id
                            if azienda_id not in aziende_dimensioni:
                                aziende_dimensioni[azienda_id] = {
                                    'azienda': rilievo.azienda,
                                    'differenza': 0.0
                                }
                            # Aggiungi la differenza (nuova dimensione - vecchia dimensione)
                            differenza = file_size_gb - old_dim
                            aziende_dimensioni[azienda_id]['differenza'] += differenza
                        
                        if old_dim == 0:
                            rilievi_senza_dimensione += 1
                        rilievi_aggiornati += 1
                    except Exception as e:
                        print(f"Errore nel calcolo dimensione per rilievo {rilievo.id}: {e}")
                        errori += 1
                else:
                    rilievi_senza_file += 1
            except Exception as e:
                print(f"Errore generale per rilievo {rilievo.id}: {e}")
                errori += 1
        
        # Aggiorna il campo giga_elab per ogni azienda
        aziende_aggiornate = 0
        for azienda_id, data in aziende_dimensioni.items():
            try:
                azienda = data['azienda']
                differenza = data['differenza']
                
                # Aggiorna giga_elab solo se c'è una differenza
                if differenza != 0:
                    azienda.giga_elab = float(azienda.giga_elab or 0) + differenza
                    # Assicurati che non vada sotto zero
                    if azienda.giga_elab < 0:
                        azienda.giga_elab = 0.0
                    azienda.save()
                    aziende_aggiornate += 1
            except Exception as e:
                print(f"Errore nell'aggiornamento azienda {azienda_id}: {e}")
        
        # Messaggio di successo
        messages.success(
            request,
            f'Calcolo dimensioni completato! '
            f'Rilievi aggiornati: {rilievi_aggiornati}/{totale_rilievi}, '
            f'Rilievi senza file: {rilievi_senza_file}, '
            f'Rilievi senza dimensione precedente: {rilievi_senza_dimensione}, '
            f'Errori: {errori}, '
            f'Aziende aggiornate: {aziende_aggiornate}'
        )
    except Exception as e:
        messages.error(request, f'Errore durante il calcolo delle dimensioni: {str(e)}')
    
    return redirect('admin_dashboard')


@login_required
def test_metrics(request):
    """Pagina di test per verificare le metriche"""
    if not request.user.is_superuser:
        return redirect('home')
    
    metrics = get_system_metrics()
    
    # Test manuale delle metriche
    test_results = {
        'psutil_available': 'psutil' not in str(metrics.get('error', '')),
        'cpu_percent': metrics.get('cpu_percent', 0),
        'memory_percent': metrics.get('memory_percent', 0),
        'disk_percent': metrics.get('disk_percent', 0),
        'platform': metrics.get('platform', 'Unknown'),
        'error': metrics.get('error', None)
    }
    
    return render(request, 'events/test_metrics.html', {
        'metrics': metrics,
        'test_results': test_results
    })


@login_required
def download_users_csv(request):
    """Scarica CSV con tutti gli utenti e le loro informazioni - Solo per admin"""
    if not request.user.is_superuser:
        return redirect('home')
    
    # Crea la risposta HTTP
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="utenti_deepgeo.csv"'
    
    # Crea il writer CSV
    writer = csv.writer(response)
    
    # Scrivi l'header
    writer.writerow([
        'ID', 'Username', 'Email', 'Nome', 'Cognome', 
        'Data Registrazione', 'Ultimo Accesso', 'Attivo', 'Staff', 'Superuser',
        'Azienda Associata', 'ID Azienda'
    ])
    
    # Scrivi i dati degli utenti
    users = User.objects.select_related('userprofile__azienda').all().order_by('id')
    for user in users:
        # Ottieni i dati del profilo utente
        try:
            user_profile = user.userprofile
            azienda_nome = user_profile.azienda.nome_azienda if user_profile.azienda else 'Nessuna'
            azienda_id = user_profile.azienda.id if user_profile.azienda else 'N/A'
        except UserProfile.DoesNotExist:
            azienda_nome = 'Nessuna'
            azienda_id = 'N/A'
        
        writer.writerow([
            user.id,
            user.username,
            user.email,
            user.first_name,
            user.last_name,
            user.date_joined.strftime('%d/%m/%Y %H:%M'),
            user.last_login.strftime('%d/%m/%Y %H:%M') if user.last_login else 'Mai',
            'Sì' if user.is_active else 'No',
            'Sì' if user.is_staff else 'No',
            'Sì' if user.is_superuser else 'No',
            azienda_nome,
            azienda_id
        ])
    
    return response


@login_required
def download_companies_csv(request):
    """Scarica CSV con tutte le aziende e le loro informazioni - Solo per admin"""
    if not request.user.is_superuser:
        return redirect('home')
    
    # Crea la risposta HTTP
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="aziende_deepgeo.csv"'
    
    # Crea il writer CSV
    writer = csv.writer(response)
    
    # Scrivi l'header
    writer.writerow([
        'ID', 'Nome Azienda', 'Partita IVA', 'Email Referente', 'Telefono Referente', 
        'PEC', 'Indirizzo Legale', 'Giga Elaborazione', 'M2 Elaborazione',
        'Tempo Medio Elaborazione', 'Tempo Totale Elaborazione', 'Metri Lineari Rilievi'
    ])
    
    # Scrivi i dati delle aziende
    companies = Azienda.objects.all().order_by('id')
    for company in companies:
        writer.writerow([
            company.id,
            company.nome_azienda,
            company.partita_iva,
            company.mail_referente,
            company.telefono_referente,
            company.pec,
            company.indirizzo_legale,
            company.giga_elab,
            company.m2_elab,
            company.tempo_medio_elab,
            company.tempo_tot_elab,
            company.metri_lineari_ril
        ])
    
    return response


@login_required
def change_password(request):
    """Pagina per cambiare la password dell'utente"""
    if request.method == 'POST':
        form = PasswordChangeForm(request.user, request.POST)
        if form.is_valid():
            user = form.save()
            update_session_auth_hash(request, user)  # Mantiene la sessione attiva
            messages.success(request, _('Password cambiata con successo!'))
            return redirect('home')
        else:
            messages.error(request, _('Si è verificato un errore. Controlla i dati inseriti.'))
    else:
        form = PasswordChangeForm(request.user)
    
    return render(request, 'events/change_password.html', {
        'form': form
    })


