import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; import 'global_data.dart'; import 'models.dart'; class CidDataManager { // =========================================================================== // METODI PER SCAMBIO DATI (QR/P2P) // =========================================================================== static Map estraiDatiPerExport() { String lato = GlobalData.latoCorrente; String val(String vA, String vB, String l) => l == 'A' ? vA : vB; bool valB(bool bA, bool bB, String l) => l == 'A' ? bA : bB; return { 'lato': lato, 'generali': { 'data': GlobalData.data_incidente, 'ora': GlobalData.ora, 'luogo': GlobalData.luogo, 'feriti': GlobalData.feriti, 'testimoni': GlobalData.testimoni, 'danni_materiali': GlobalData.Veicoli_danni_materiali_oltre, 'oggetti_diversi': GlobalData.Oggetti_diversi_danni_materiali, }, 'circostanze': _serializeCircostanze(lato == 'A' ? GlobalData.circostanzeA : GlobalData.circostanzeB), 'punti_urto': lato == 'A' ? GlobalData.puntiUrtoA_List : GlobalData.puntiUrtoB_List, // CASSETTO 1: GRAFICO INCIDENTE (Strade, Auto) 'grafico': { 'tratti_dinamica': GlobalData.tratti.map((t) => t.toMap()).toList(), 'elementi_dinamica': GlobalData.elementi.map((e) => e.toMap()).toList(), }, // CASSETTO 2: FIRMA (Dati grafici personali) 'firma': _serializePunti(lato == 'A' ? GlobalData.puntiFirmaA : GlobalData.puntiFirmaB), 'contraente': { 'cognome': val(GlobalData.Cognome_contraente_A, GlobalData.Cognome_contraente_B, lato), 'nome': val(GlobalData.Nome_contraente_A, GlobalData.Nome_contraente_B, lato), 'cf': val(GlobalData.Codice_Fiscale_contraente_A, GlobalData.Codice_Fiscale_contraente_B, lato), 'indirizzo': val(GlobalData.Indirizzo_contraente_A, GlobalData.Indirizzo_contraente_B, lato), 'cap': val(GlobalData.CAP_contraente_A, GlobalData.CAP_contraente_B, lato), 'stato': val(GlobalData.Stato_contraente_A, GlobalData.Stato_contraente_B, lato), 'tel': val(GlobalData.N_telefono_mail_contraente_A, GlobalData.N_telefono_mail_contraente_B, lato), }, 'veicolo': { 'marca': val(GlobalData.Marca_e_Tipo_A, GlobalData.Marca_e_Tipo_B, lato), 'targa': val(GlobalData.Targa_A, GlobalData.Targa_B, lato), 'stato_imm': val(GlobalData.Stato_immatricolazione_A, GlobalData.Stato_immatricolazione_B, lato), 'stato_imm2': val(GlobalData.Stato_immatricolazione2_A, GlobalData.Stato_immatricolazione2_B, lato), 'rimorchio': val(GlobalData.Rimorchio_A, GlobalData.Rimorchio_B, lato), }, 'assicurazione': { 'denominazione': val(GlobalData.Denominazione_A, GlobalData.Denominazione_B, lato), 'polizza': val(GlobalData.Numero_Polizza_A, GlobalData.Numero_Polizza_B, lato), 'agenzia': val(GlobalData.Agenzia_A, GlobalData.Agenzia_B, lato), 'denom_agenzia': val(GlobalData.Denominazione_agenzia_A, GlobalData.Denominazione_agenzia_B, lato), 'indirizzo_agenzia': val(GlobalData.Indirizzo_agenzia_A, GlobalData.Indirizzo_agenzia_B, lato), 'stato_agenzia': val(GlobalData.Stato_agenzia_A, GlobalData.Stato_agenzia_B, lato), 'tel_agenzia': val(GlobalData.N_tel_mail_agenzia_A, GlobalData.N_tel_mail_agenzia_B, lato), 'carta_verde': val(GlobalData.N_carta_verde_A, GlobalData.N_carta_verde_B, lato), 'validita_dal': val(GlobalData.Data_Inizio_Dal_A, GlobalData.Data_Inizio_Dal_B, lato), 'validita_al': val(GlobalData.Data_Scadenza_Al_A, GlobalData.Data_Scadenza_Al_B, lato), 'flag_danni': valB(GlobalData.FLAG_danni_mat_assicurati_A, GlobalData.FLAG_danni_mat_assicurati_B, lato), }, 'conducente': { 'cognome': val(GlobalData.Cognome_cond_A, GlobalData.Cognome_cond_B, lato), 'nome': val(GlobalData.Nome_cond_A, GlobalData.Nome_cond_B, lato), 'nascita': val(GlobalData.Data_nascita_cond_A, GlobalData.Data_nascita_cond_B, lato), 'cf': val(GlobalData.Cod_fiscale_cond_A, GlobalData.Cod_fiscale_cond_B, lato), 'indirizzo': val(GlobalData.Indirizzo_cond_A, GlobalData.Indirizzo_cond_B, lato), 'stato': val(GlobalData.Stato_cond_A, GlobalData.Stato_cond_B, lato), 'tel': val(GlobalData.N_tel_mail_cond_A, GlobalData.N_tel_mail_cond_B, lato), 'patente': val(GlobalData.N_Patente_cond_A, GlobalData.N_Patente_cond_B, lato), 'cat_patente': val(GlobalData.Categoria_cond_A, GlobalData.Categoria_cond_B, lato), 'scad_patente': val(GlobalData.Scadenza_cond_A, GlobalData.Scadenza_cond_B, lato), }, 'danni_osservazioni': { 'visibili': val(GlobalData.danni_visibili_A, GlobalData.danni_visibili_B, lato), 'osservazioni': val(GlobalData.osservazioni_A, GlobalData.osservazioni_B, lato), } }; } static void importaDati(Map data) { String latoRemoto = data['lato'] ?? 'B'; // 1. Dati Comuni if (data['generali'] != null) { var gen = data['generali']; if ((gen['data'] ?? "").isNotEmpty) GlobalData.data_incidente = gen['data']; if ((gen['ora'] ?? "").isNotEmpty) GlobalData.ora = gen['ora']; if ((gen['luogo'] ?? "").isNotEmpty) GlobalData.luogo = gen['luogo']; if (gen['feriti'] != null) GlobalData.feriti = gen['feriti']; if (gen['testimoni'] != null) GlobalData.testimoni = gen['testimoni']; if (gen['danni_materiali'] != null) GlobalData.Veicoli_danni_materiali_oltre = gen['danni_materiali']; if (gen['oggetti_diversi'] != null) GlobalData.Oggetti_diversi_danni_materiali = gen['oggetti_diversi']; } // --- PROTEZIONE GRAFICO (CASSETTO 1) --- // Solo se i dati arrivano da A, permettiamo di sovrascrivere il grafico comune. // Se arrivano da B, IGNORIAMO questa chiave (così il disegno di A resta intatto). if (latoRemoto == 'A' && data['grafico'] != null) { var graf = data['grafico']; if (graf['tratti_dinamica'] != null) { List listRaw = graf['tratti_dinamica']; GlobalData.tratti = listRaw.map((x) => TrattoPenna.fromMap(x)).toList(); } if (graf['elementi_dinamica'] != null) { List listRaw = graf['elementi_dinamica']; GlobalData.elementi = listRaw.map((x) => ElementoGrafico.fromMap(x)).toList(); } } // --- PROTEZIONE FIRMA (CASSETTO 2) --- // La firma NON viene bloccata. Ognuno ha la sua firma e deve poterla inviare. // Viene salvata in variabili distinte (puntiFirmaA e puntiFirmaB). if (data['firma'] != null) { List puntiFirma = _deserializePunti(data['firma']); if (latoRemoto == 'A') GlobalData.puntiFirmaA = puntiFirma; else GlobalData.puntiFirmaB = puntiFirma; // Qui B salva la sua firma } // 3. Circostanze if (data['circostanze'] != null) { Map rawCirc = data['circostanze']; Map mappaCirc = {}; rawCirc.forEach((k, v) => mappaCirc[int.tryParse(k) ?? 0] = v as bool); if (latoRemoto == 'A') GlobalData.circostanzeA = mappaCirc; else GlobalData.circostanzeB = mappaCirc; } // 4. Punti Urto if (data['punti_urto'] != null) { List puntiRecuperati = List.from(data['punti_urto']); if (latoRemoto == 'A') { GlobalData.puntiUrtoA_List = puntiRecuperati; } else { GlobalData.puntiUrtoB_List = puntiRecuperati; } } void setVal(Function(String) setA, Function(String) setB, dynamic val) { if (val == null) return; if (latoRemoto == 'A') setA(val.toString()); else setB(val.toString()); } void setBool(Function(bool) setA, Function(bool) setB, dynamic val) { if (val == null) return; if (latoRemoto == 'A') setA(val as bool); else setB(val as bool); } if (data['contraente'] != null) { var c = data['contraente']; setVal((v) => GlobalData.Cognome_contraente_A = v, (v) => GlobalData.Cognome_contraente_B = v, c['cognome']); setVal((v) => GlobalData.Nome_contraente_A = v, (v) => GlobalData.Nome_contraente_B = v, c['nome']); setVal((v) => GlobalData.Codice_Fiscale_contraente_A = v, (v) => GlobalData.Codice_Fiscale_contraente_B = v, c['cf']); setVal((v) => GlobalData.Indirizzo_contraente_A = v, (v) => GlobalData.Indirizzo_contraente_B = v, c['indirizzo']); setVal((v) => GlobalData.CAP_contraente_A = v, (v) => GlobalData.CAP_contraente_B = v, c['cap']); setVal((v) => GlobalData.Stato_contraente_A = v, (v) => GlobalData.Stato_contraente_B = v, c['stato']); setVal((v) => GlobalData.N_telefono_mail_contraente_A = v, (v) => GlobalData.N_telefono_mail_contraente_B = v, c['tel']); } if (data['veicolo'] != null) { var v = data['veicolo']; setVal((v) => GlobalData.Marca_e_Tipo_A = v, (v) => GlobalData.Marca_e_Tipo_B = v, v['marca']); setVal((v) => GlobalData.Targa_A = v, (v) => GlobalData.Targa_B = v, v['targa']); setVal((v) => GlobalData.Stato_immatricolazione_A = v, (v) => GlobalData.Stato_immatricolazione_B = v, v['stato_imm']); setVal((v) => GlobalData.Stato_immatricolazione2_A = v, (v) => GlobalData.Stato_immatricolazione2_B = v, v['stato_imm2']); setVal((v) => GlobalData.Rimorchio_A = v, (v) => GlobalData.Rimorchio_B = v, v['rimorchio']); } if (data['assicurazione'] != null) { var a = data['assicurazione']; setVal((v) => GlobalData.Denominazione_A = v, (v) => GlobalData.Denominazione_B = v, a['denominazione']); setVal((v) => GlobalData.Numero_Polizza_A = v, (v) => GlobalData.Numero_Polizza_B = v, a['polizza']); setVal((v) => GlobalData.Agenzia_A = v, (v) => GlobalData.Agenzia_B = v, a['agenzia']); setVal((v) => GlobalData.Denominazione_agenzia_A = v, (v) => GlobalData.Denominazione_agenzia_B = v, a['denom_agenzia']); setVal((v) => GlobalData.Indirizzo_agenzia_A = v, (v) => GlobalData.Indirizzo_agenzia_B = v, a['indirizzo_agenzia']); setVal((v) => GlobalData.Stato_agenzia_A = v, (v) => GlobalData.Stato_agenzia_B = v, a['stato_agenzia']); setVal((v) => GlobalData.N_tel_mail_agenzia_A = v, (v) => GlobalData.N_tel_mail_agenzia_B = v, a['tel_agenzia']); setVal((v) => GlobalData.N_carta_verde_A = v, (v) => GlobalData.N_carta_verde_B = v, a['carta_verde']); setVal((v) => GlobalData.Data_Inizio_Dal_A = v, (v) => GlobalData.Data_Inizio_Dal_B = v, a['validita_dal']); setVal((v) => GlobalData.Data_Scadenza_Al_A = v, (v) => GlobalData.Data_Scadenza_Al_B = v, a['validita_al']); setBool((v) => GlobalData.FLAG_danni_mat_assicurati_A = v, (v) => GlobalData.FLAG_danni_mat_assicurati_B = v, a['flag_danni']); } if (data['conducente'] != null) { var c = data['conducente']; setVal((v) => GlobalData.Cognome_cond_A = v, (v) => GlobalData.Cognome_cond_B = v, c['cognome']); setVal((v) => GlobalData.Nome_cond_A = v, (v) => GlobalData.Nome_cond_B = v, c['nome']); setVal((v) => GlobalData.Data_nascita_cond_A = v, (v) => GlobalData.Data_nascita_cond_B = v, c['nascita']); setVal((v) => GlobalData.Cod_fiscale_cond_A = v, (v) => GlobalData.Cod_fiscale_cond_B = v, c['cf']); setVal((v) => GlobalData.Indirizzo_cond_A = v, (v) => GlobalData.Indirizzo_cond_B = v, c['indirizzo']); setVal((v) => GlobalData.Stato_cond_A = v, (v) => GlobalData.Stato_cond_B = v, c['stato']); setVal((v) => GlobalData.N_tel_mail_cond_A = v, (v) => GlobalData.N_tel_mail_cond_B = v, c['tel']); setVal((v) => GlobalData.N_Patente_cond_A = v, (v) => GlobalData.N_Patente_cond_B = v, c['patente']); setVal((v) => GlobalData.Categoria_cond_A = v, (v) => GlobalData.Categoria_cond_B = v, c['cat_patente']); setVal((v) => GlobalData.Scadenza_cond_A = v, (v) => GlobalData.Scadenza_cond_B = v, c['scad_patente']); } if (data['danni_osservazioni'] != null) { var d = data['danni_osservazioni']; setVal((v) => GlobalData.danni_visibili_A = v, (v) => GlobalData.danni_visibili_B = v, d['visibili']); setVal((v) => GlobalData.osservazioni_A = v, (v) => GlobalData.osservazioni_B = v, d['osservazioni']); } } // =========================================================================== // METODI PER SALVATAGGIO CLOUD (FIREBASE) // =========================================================================== static Future salvaDati(String sessionId, String lato) async { final docRef = FirebaseFirestore.instance.collection('scambi_cid').doc(sessionId); // Estrae tutti i dati dalla memoria locale Map datiExport = estraiDatiPerExport(); // Prepariamo i dati da inviare al server Map updateData = { 'generali': datiExport['generali'], 'lato_$lato': { ...datiExport['contraente'], ...datiExport['veicolo'], ...datiExport['assicurazione'], ...datiExport['conducente'], 'danni_visibili': datiExport['danni_osservazioni']['visibili'], 'osservazioni': datiExport['danni_osservazioni']['osservazioni'], 'circostanze': datiExport['circostanze'], 'punti_urto': datiExport['punti_urto'], 'firma': datiExport['firma'], // <-- La firma è dentro "lato_A" o "lato_B", quindi è al sicuro 'completo': true, }, 'timestamp': FieldValue.serverTimestamp(), }; // --- PROTEZIONE AGGIUNTIVA PER IL CLOUD --- // Il GRAFICO lo aggiorniamo nel DB solo se siamo il LATO A. // Il LATO B non ha diritto di toccare questa chiave. if (lato == 'A') { updateData['grafico'] = datiExport['grafico']; } await docRef.set(updateData, SetOptions(merge: true)); return sessionId; } // --- METODO RECUPERA DATI CLOUD --- static Future caricaDati(String sessionId, String latoDaCaricare) async { final doc = await FirebaseFirestore.instance.collection('scambi_cid').doc(sessionId).get(); if (!doc.exists) return; final data = doc.data()!; Map datiDaImportare = {}; datiDaImportare['lato'] = latoDaCaricare; if (data['generali'] != null) datiDaImportare['generali'] = data['generali']; if (data['grafico'] != null) datiDaImportare['grafico'] = data['grafico']; if (data['lato_$latoDaCaricare'] != null) { Map latoData = data['lato_$latoDaCaricare']; datiDaImportare['contraente'] = latoData; datiDaImportare['veicolo'] = latoData; datiDaImportare['assicurazione'] = latoData; datiDaImportare['conducente'] = latoData; datiDaImportare['danni_osservazioni'] = { 'visibili': latoData['danni_visibili'], 'osservazioni': latoData['osservazioni'], }; datiDaImportare['circostanze'] = latoData['circostanze']; datiDaImportare['punti_urto'] = latoData['punti_urto']; datiDaImportare['firma'] = latoData['firma']; // Recupera la firma specifica dal lato } importaDati(datiDaImportare); } // =========================================================================== // HELPER SERIALIZZAZIONE // =========================================================================== static Map _serializeCircostanze(Map circ) { return circ.map((key, value) => MapEntry(key.toString(), value)); } static List> _serializePunti(List punti) { List> res = []; for (var p in punti) { if (p != null) res.add({'dx': p.dx, 'dy': p.dy}); } return res; } static List _deserializePunti(dynamic lista) { if (lista is! List) return []; return lista.map((item) { if (item == null) return null; return Offset((item['dx'] as num).toDouble(), (item['dy'] as num).toDouble()); }).toList(); } }