import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../models/network/network_device.dart'; import '../../models/network/network_link.dart'; import '../../models/network/network_port.dart'; import '../../models/network/network_vlan.dart'; import '../supabase_provider.dart'; final networkDevicesProvider = FutureProvider>((ref) async { final client = ref.watch(supabaseClientProvider); final rows = await client.from('network_devices').select().order('name'); return (rows as List) .map((r) => NetworkDevice.fromMap(r as Map)) .toList(); }); final networkPortsProvider = FutureProvider>((ref) async { final client = ref.watch(supabaseClientProvider); final rows = await client.from('network_ports').select().order('port_number'); return (rows as List) .map((r) => NetworkPort.fromMap(r as Map)) .toList(); }); final networkLinksProvider = FutureProvider>((ref) async { final client = ref.watch(supabaseClientProvider); final rows = await client.from('network_links').select(); return (rows as List) .map((r) => NetworkLink.fromMap(r as Map)) .toList(); }); final networkVlansProvider = FutureProvider>((ref) async { final client = ref.watch(supabaseClientProvider); final rows = await client.from('network_vlans').select().order('vlan_id'); return (rows as List) .map((r) => NetworkVlan.fromMap(r as Map)) .toList(); }); final networkDeviceByIdProvider = FutureProvider.family((ref, id) async { final client = ref.watch(supabaseClientProvider); final row = await client .from('network_devices') .select() .eq('id', id) .maybeSingle(); if (row == null) return null; return NetworkDevice.fromMap(row); }); final networkPortsByDeviceProvider = FutureProvider.family, String>((ref, deviceId) async { final client = ref.watch(supabaseClientProvider); final rows = await client .from('network_ports') .select() .eq('device_id', deviceId) .order('port_number'); return (rows as List) .map((r) => NetworkPort.fromMap(r as Map)) .toList(); }); class NetworkDevicesController { NetworkDevicesController(this.ref); final Ref ref; Future createDevice({ required String name, required NetworkDeviceKind kind, NetworkDeviceRole? role, String? vendor, String? model, String? serial, String? mgmtIp, String? mac, String? locationId, NetworkImportSource importSource = NetworkImportSource.manual, NetworkDeviceStatus status = NetworkDeviceStatus.unknown, String? notes, }) async { final client = ref.read(supabaseClientProvider); final inserted = await client .from('network_devices') .insert({ 'name': name, 'kind': kind.wire, 'role': ?role?.wire, 'vendor': ?vendor, 'model': ?model, 'serial': ?serial, 'mgmt_ip': ?mgmtIp, 'mac': ?mac, 'location_id': ?locationId, 'import_source': importSource.wire, 'status': status.wire, 'notes': ?notes, }) .select() .single(); ref.invalidate(networkDevicesProvider); return NetworkDevice.fromMap(inserted); } Future updateDevice(NetworkDevice device) async { final client = ref.read(supabaseClientProvider); await client .from('network_devices') .update(device.toUpdateMap()) .eq('id', device.id); ref.invalidate(networkDevicesProvider); ref.invalidate(networkDeviceByIdProvider(device.id)); } Future deleteDevice(String id) async { final client = ref.read(supabaseClientProvider); await client.from('network_devices').delete().eq('id', id); ref.invalidate(networkDevicesProvider); ref.invalidate(networkPortsProvider); ref.invalidate(networkLinksProvider); } Future createPort({ required String deviceId, required String portNumber, NetworkPortKind? portKind, int? speedMbps, int? accessVlan, bool isTrunk = false, List trunkVlans = const [], String? notes, }) async { final client = ref.read(supabaseClientProvider); final inserted = await client .from('network_ports') .insert({ 'device_id': deviceId, 'port_number': portNumber, 'port_kind': ?portKind?.wire, 'speed_mbps': ?speedMbps, 'access_vlan': ?accessVlan, 'is_trunk': isTrunk, if (trunkVlans.isNotEmpty) 'trunk_vlans': trunkVlans, 'notes': ?notes, }) .select() .single(); ref.invalidate(networkPortsProvider); ref.invalidate(networkPortsByDeviceProvider(deviceId)); return NetworkPort.fromMap(inserted); } Future deletePort(String id, {String? deviceId}) async { final client = ref.read(supabaseClientProvider); await client.from('network_ports').delete().eq('id', id); ref.invalidate(networkPortsProvider); ref.invalidate(networkLinksProvider); if (deviceId != null) { ref.invalidate(networkPortsByDeviceProvider(deviceId)); } } Future updatePort({ required String id, required String deviceId, required String portNumber, NetworkPortKind? portKind, int? speedMbps, int? accessVlan, bool isTrunk = false, List trunkVlans = const [], String? notes, }) async { final client = ref.read(supabaseClientProvider); await client.from('network_ports').update({ 'port_number': portNumber, 'port_kind': portKind?.wire, 'speed_mbps': speedMbps, 'access_vlan': accessVlan, 'is_trunk': isTrunk, 'trunk_vlans': trunkVlans.isEmpty ? null : trunkVlans, 'notes': notes, }).eq('id', id); ref.invalidate(networkPortsProvider); ref.invalidate(networkPortsByDeviceProvider(deviceId)); } Future createLink({ required String portA, required String portB, NetworkLinkKind? linkKind, String? cableLabel, String? notes, }) async { final client = ref.read(supabaseClientProvider); final inserted = await client .from('network_links') .insert(NetworkLink.insertMapFor( portA: portA, portB: portB, linkKind: linkKind, cableLabel: cableLabel, notes: notes, )) .select() .single(); ref.invalidate(networkLinksProvider); return NetworkLink.fromMap(inserted); } Future deleteLink(String id) async { final client = ref.read(supabaseClientProvider); await client.from('network_links').delete().eq('id', id); ref.invalidate(networkLinksProvider); } Future createVlan({ required int vlanId, required String name, String? description, String? color, }) async { final client = ref.read(supabaseClientProvider); final inserted = await client .from('network_vlans') .insert({ 'vlan_id': vlanId, 'name': name, 'description': ?description, 'color': ?color, }) .select() .single(); ref.invalidate(networkVlansProvider); return NetworkVlan.fromMap(inserted); } Future deleteVlan(String id) async { final client = ref.read(supabaseClientProvider); await client.from('network_vlans').delete().eq('id', id); ref.invalidate(networkVlansProvider); } } final networkDevicesControllerProvider = Provider((ref) => NetworkDevicesController(ref));