DB::table('comuni_italiani')->count(), 'regioni_totali' => DB::table('comuni_italiani')->distinct('regione')->count(), 'province_totali' => DB::table('comuni_italiani')->distinct('provincia')->count(), 'ultimo_aggiornamento' => DB::table('comuni_italiani')->max('updated_at') ]; return view('superadmin.comuni.index', compact('stats')); } /** * Upload e importazione ZIP con dati comuni */ public function uploadZip(Request $request) { $request->validate([ 'zip_file' => 'required|file|mimes:zip|max:50000', // Max 50MB 'overwrite' => 'nullable|boolean' ]); try { $zipFile = $request->file('zip_file'); $tempPath = storage_path('app/temp/comuni_import_' . time()); // Crea directory temporanea if (!file_exists($tempPath)) { mkdir($tempPath, 0755, true); } // Estrai il ZIP $zip = new \ZipArchive; if ($zip->open($zipFile->getPathname()) === TRUE) { $zip->extractTo($tempPath); $zip->close(); // Cerca file JSON nella directory estratta $jsonFiles = glob($tempPath . '/*.json'); if (empty($jsonFiles)) { throw new \Exception('Nessun file JSON trovato nel ZIP'); } $importedCount = 0; $skippedCount = 0; foreach ($jsonFiles as $jsonFile) { $result = $this->importJsonFile($jsonFile, $request->boolean('overwrite')); $importedCount += $result['imported']; $skippedCount += $result['skipped']; } // Pulizia file temporanei $this->cleanupTempFiles($tempPath); return response()->json([ 'success' => true, 'message' => "Importazione completata: {$importedCount} comuni importati, {$skippedCount} saltati", 'imported' => $importedCount, 'skipped' => $skippedCount ]); } else { throw new \Exception('Impossibile aprire il file ZIP'); } } catch (\Exception $e) { Log::error('Errore import comuni ZIP: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Errore durante l\'importazione: ' . $e->getMessage() ], 500); } } /** * Importa singolo file JSON */ private function importJsonFile($jsonFile, $overwrite = false) { $jsonData = json_decode(file_get_contents($jsonFile), true); if (!$jsonData) { throw new \Exception('File JSON non valido: ' . basename($jsonFile)); } $imported = 0; $skipped = 0; foreach ($jsonData as $comune) { // Validazione dati minimi if (!isset($comune['codice_catastale']) || !isset($comune['denominazione'])) { $skipped++; continue; } $exists = DB::table('comuni_italiani') ->where('codice_catastale', $comune['codice_catastale']) ->exists(); if ($exists && !$overwrite) { $skipped++; continue; } // Prepara dati per inserimento/aggiornamento $data = [ 'codice_catastale' => $comune['codice_catastale'], 'denominazione' => $comune['denominazione'], 'regione' => $comune['regione'] ?? null, 'provincia' => $comune['provincia'] ?? null, 'cap' => $comune['cap'] ?? null, 'codice_istat' => $comune['codice_istat'] ?? null, 'prefisso' => $comune['prefisso'] ?? null, 'superficie_kmq' => $comune['superficie_kmq'] ?? null, 'popolazione' => $comune['popolazione'] ?? null, 'latitudine' => $comune['latitudine'] ?? null, 'longitudine' => $comune['longitudine'] ?? null, 'zona_altimetrica' => $comune['zona_altimetrica'] ?? null, 'updated_at' => now(), ]; if ($exists && $overwrite) { DB::table('comuni_italiani') ->where('codice_catastale', $comune['codice_catastale']) ->update($data); } else { $data['created_at'] = now(); DB::table('comuni_italiani')->insert($data); } $imported++; } return ['imported' => $imported, 'skipped' => $skipped]; } /** * Ricerca comuni AJAX */ public function search(Request $request) { $query = $request->get('q', ''); $regione = $request->get('regione', ''); $provincia = $request->get('provincia', ''); $comuni = DB::table('comuni_italiani') ->when($query, function($q) use ($query) { return $q->where('denominazione', 'LIKE', "%{$query}%") ->orWhere('codice_catastale', 'LIKE', "%{$query}%"); }) ->when($regione, function($q) use ($regione) { return $q->where('regione', $regione); }) ->when($provincia, function($q) use ($provincia) { return $q->where('provincia', $provincia); }) ->orderBy('denominazione') ->limit(50) ->get(); return response()->json($comuni); } /** * Statistiche dettagliate */ public function stats() { $stats = [ 'per_regione' => DB::table('comuni_italiani') ->select('regione', DB::raw('count(*) as totale')) ->groupBy('regione') ->orderBy('totale', 'desc') ->get(), 'per_provincia' => DB::table('comuni_italiani') ->select('provincia', DB::raw('count(*) as totale')) ->groupBy('provincia') ->orderBy('totale', 'desc') ->limit(20) ->get(), 'totali' => [ 'comuni' => DB::table('comuni_italiani')->count(), 'regioni' => DB::table('comuni_italiani')->distinct('regione')->count(), 'province' => DB::table('comuni_italiani')->distinct('provincia')->count(), ] ]; return response()->json($stats); } /** * Elimina tutti i comuni (reset database) */ public function reset(Request $request) { if (!$request->has('confirm') || $request->get('confirm') !== 'RESET_COMUNI') { return response()->json([ 'success' => false, 'message' => 'Conferma richiesta mancante' ], 400); } try { $deletedCount = DB::table('comuni_italiani')->count(); DB::table('comuni_italiani')->truncate(); Log::info("SuperAdmin reset comuni italiani: {$deletedCount} record eliminati"); return response()->json([ 'success' => true, 'message' => "Database comuni resettato: {$deletedCount} record eliminati" ]); } catch (\Exception $e) { Log::error('Errore reset comuni: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Errore durante il reset: ' . $e->getMessage() ], 500); } } /** * Pulisce i file temporanei */ private function cleanupTempFiles($tempPath) { if (is_dir($tempPath)) { $files = array_diff(scandir($tempPath), ['.', '..']); foreach ($files as $file) { unlink($tempPath . '/' . $file); } rmdir($tempPath); } } /** * Export comuni in formato JSON */ public function export(Request $request) { $regione = $request->get('regione'); $provincia = $request->get('provincia'); $query = DB::table('comuni_italiani'); if ($regione) { $query->where('regione', $regione); } if ($provincia) { $query->where('provincia', $provincia); } $comuni = $query->orderBy('denominazione')->get(); $filename = 'comuni_italiani_' . date('Y-m-d_H-i-s') . '.json'; return response()->json($comuni) ->header('Content-Disposition', 'attachment; filename="' . $filename . '"'); } }