import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; import '../../core/constants/app_constants.dart'; import '../../core/theme/app_theme.dart'; import '../../data/models/weapon.dart'; import '../../data/models/maintenance.dart'; import '../../data/repositories/session_repository.dart'; class WeaponDetailScreen extends StatefulWidget { final Weapon weapon; const WeaponDetailScreen({super.key, required this.weapon}); @override State createState() => _WeaponDetailScreenState(); } class _WeaponDetailScreenState extends State { late Weapon _weapon; List _maintenance = []; int _totalRounds = 0; bool _isLoading = true; @override void initState() { super.initState(); _weapon = widget.weapon; _loadData(); } Future _loadData() async { final repository = context.read(); final history = await repository.getMaintenanceHistory(_weapon.id); final rounds = await repository.getRoundsFiredForWeapon(_weapon.id); if (mounted) { setState(() { _maintenance = history; _totalRounds = rounds; _isLoading = false; }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(_weapon.customName ?? _weapon.name), actions: [ IconButton( icon: const Icon(Icons.edit), onPressed: () => _showEditWeaponDialog(context), ), ], ), body: _isLoading ? const Center(child: CircularProgressIndicator()) : SingleChildScrollView( padding: const EdgeInsets.all(AppConstants.defaultPadding), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _buildStatsSection(), const SizedBox(height: 24), _buildInfoCard(), const SizedBox(height: 24), _buildOptionsCard(), const SizedBox(height: 24), _buildHistorySection(), ], ), ), floatingActionButton: FloatingActionButton.extended( onPressed: () => _showAddMaintenanceDialog(context), label: const Text('Entretien'), icon: const Icon(Icons.build), ), ); } Widget _buildStatsSection() { return Row( children: [ Expanded( child: _buildStatCard( 'Total Tirs', _totalRounds.toString(), Icons.ads_click, AppTheme.primaryColor, ), ), const SizedBox(width: 16), Expanded( child: _buildStatCard( 'Sessions', 'N/A', Icons.history, Colors.orange, ), ), ], ); } Widget _buildStatCard(String label, String value, IconData icon, Color color) { return Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ Icon(icon, color: color), const SizedBox(height: 8), Text(value, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), Text(label, style: const TextStyle(fontSize: 12, color: Colors.grey)), ], ), ), ); } Widget _buildInfoCard() { return Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Informations techniques', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16)), const Divider(), _buildInfoRow('Modèle', _weapon.name), _buildInfoRow('Type', _weapon.type.displayName), _buildInfoRow('Calibre', _weapon.caliber), _buildInfoRow('Chargeurs', '${_weapon.magazineCount} x ${_weapon.magazineCapacity} coups'), if (_weapon.notes != null && _weapon.notes!.isNotEmpty) ...[ const SizedBox(height: 8), const Text('Notes:', style: TextStyle(fontWeight: FontWeight.w500)), Text(_weapon.notes!, style: const TextStyle(color: Colors.grey)), ], ], ), ), ); } Widget _buildOptionsCard() { return Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Options & Personnalisation', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16)), const Divider(), _buildInfoRow('Optique / Lunette', _weapon.optic ?? 'Mire fer'), _buildInfoRow('Modérateur / Silencieux', _weapon.silencer ?? 'Aucun'), _buildInfoRow('Détente', _weapon.trigger ?? 'Standard'), if (_weapon.customName != null) _buildInfoRow('Surnom', _weapon.customName!), ], ), ), ); } Widget _buildInfoRow(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(label, style: const TextStyle(color: Colors.grey)), Text(value, style: const TextStyle(fontWeight: FontWeight.w500)), ], ), ); } Widget _buildHistorySection() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Historique d\'entretien', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18)), const SizedBox(height: 8), if (_maintenance.isEmpty) const Padding( padding: EdgeInsets.symmetric(vertical: 24.0), child: Center(child: Text('Aucun entretien enregistré', style: TextStyle(color: Colors.grey))), ) else ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: _maintenance.length, itemBuilder: (context, index) { final entry = _maintenance[index]; return Card( margin: const EdgeInsets.only(bottom: 8), child: ListTile( leading: CircleAvatar( backgroundColor: _getMaintenanceColor(entry.type).withValues(alpha: 0.1), child: Icon(_getMaintenanceIcon(entry.type), color: _getMaintenanceColor(entry.type), size: 20), ), title: Text(entry.type.displayName), subtitle: Text(entry.description), trailing: Text(DateFormat('dd/MM/yy').format(entry.date), style: const TextStyle(fontSize: 12)), onLongPress: () => _confirmDeleteMaintenance(context, entry), ), ); }, ), ], ); } Color _getMaintenanceColor(MaintenanceType type) { switch (type) { case MaintenanceType.cleaning: return Colors.blue; case MaintenanceType.repair: return Colors.red; case MaintenanceType.inspection: return Colors.green; case MaintenanceType.upgrade: return Colors.purple; case MaintenanceType.other: return Colors.grey; } } IconData _getMaintenanceIcon(MaintenanceType type) { switch (type) { case MaintenanceType.cleaning: return Icons.opacity; case MaintenanceType.repair: return Icons.build; case MaintenanceType.inspection: return Icons.visibility; case MaintenanceType.upgrade: return Icons.trending_up; case MaintenanceType.other: return Icons.more_horiz; } } void _showEditWeaponDialog(BuildContext context) async { final nameController = TextEditingController(text: _weapon.name); final caliberController = TextEditingController(text: _weapon.caliber); final magCountController = TextEditingController(text: _weapon.magazineCount.toString()); final magCapController = TextEditingController(text: _weapon.magazineCapacity.toString()); final notesController = TextEditingController(text: _weapon.notes); final opticController = TextEditingController(text: _weapon.optic); final silencerController = TextEditingController(text: _weapon.silencer); final triggerController = TextEditingController(text: _weapon.trigger); final customNameController = TextEditingController(text: _weapon.customName); WeaponType selectedType = _weapon.type; final result = await showDialog( context: context, builder: (context) => StatefulBuilder( builder: (context, setState) => AlertDialog( title: const Text('Modifier l\'arme'), content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( controller: nameController, decoration: const InputDecoration(labelText: 'Modèle', hintText: 'ex: Glock 17'), ), TextField( controller: customNameController, decoration: const InputDecoration(labelText: 'Surnom / Custom Name', hintText: 'ex: Mon Glock de Compète'), ), DropdownButtonFormField( value: selectedType, decoration: const InputDecoration(labelText: 'Type'), items: WeaponType.values.map((t) => DropdownMenuItem(value: t, child: Text(t.displayName))).toList(), onChanged: (v) => setState(() => selectedType = v!), ), TextField( controller: caliberController, decoration: const InputDecoration(labelText: 'Calibre'), ), const SizedBox(height: 16), const Text('Équipement & Options', style: TextStyle(fontWeight: FontWeight.bold)), TextField( controller: opticController, decoration: const InputDecoration(labelText: 'Optique / Lunette', hintText: 'ex: Holosun 507C'), ), TextField( controller: silencerController, decoration: const InputDecoration(labelText: 'Modérateur / Silencieux'), ), TextField( controller: triggerController, decoration: const InputDecoration(labelText: 'Détente / Trigger'), ), const SizedBox(height: 16), const Text('Logistique', style: TextStyle(fontWeight: FontWeight.bold)), Row( children: [ Expanded( child: TextField( controller: magCountController, decoration: const InputDecoration(labelText: 'Chargeurs'), keyboardType: TextInputType.number, ), ), const SizedBox(width: 16), Expanded( child: TextField( controller: magCapController, decoration: const InputDecoration(labelText: 'Capacité'), keyboardType: TextInputType.number, ), ), ], ), TextField( controller: notesController, decoration: const InputDecoration(labelText: 'Notes'), maxLines: 2, ), ], ), ), actions: [ TextButton(onPressed: () => Navigator.pop(context, false), child: const Text('Annuler')), ElevatedButton(onPressed: () => Navigator.pop(context, true), child: const Text('Enregistrer')), ], ), ), ); if (result == true) { final updatedWeapon = _weapon.copyWith( name: nameController.text, type: selectedType, caliber: caliberController.text, magazineCount: int.tryParse(magCountController.text) ?? 1, magazineCapacity: int.tryParse(magCapController.text) ?? 10, notes: notesController.text, optic: opticController.text.isEmpty ? null : opticController.text, silencer: silencerController.text.isEmpty ? null : silencerController.text, trigger: triggerController.text.isEmpty ? null : triggerController.text, customName: customNameController.text.isEmpty ? null : customNameController.text, ); final repository = context.read(); await repository.updateWeapon(updatedWeapon); setState(() { _weapon = updatedWeapon; }); } } void _showAddMaintenanceDialog(BuildContext context) async { final descController = TextEditingController(); MaintenanceType selectedType = MaintenanceType.cleaning; final result = await showDialog( context: context, builder: (context) => StatefulBuilder( builder: (context, setState) => AlertDialog( title: const Text('Ajouter un entretien'), content: Column( mainAxisSize: MainAxisSize.min, children: [ DropdownButtonFormField( value: selectedType, decoration: const InputDecoration(labelText: 'Type d\'intervention'), items: MaintenanceType.values.map((t) => DropdownMenuItem(value: t, child: Text(t.displayName))).toList(), onChanged: (v) => setState(() => selectedType = v!), ), TextField( controller: descController, decoration: const InputDecoration(labelText: 'Description', hintText: 'ex: Nettoyage complet après séance'), maxLines: 2, ), ], ), actions: [ TextButton(onPressed: () => Navigator.pop(context, false), child: const Text('Annuler')), ElevatedButton(onPressed: () => Navigator.pop(context, true), child: const Text('Ajouter')), ], ), ), ); if (result == true && descController.text.isNotEmpty) { final repository = context.read(); await repository.addMaintenanceEntry( weaponId: _weapon.id, type: selectedType, description: descController.text, roundsSinceLast: _totalRounds, ); _loadData(); } } void _confirmDeleteMaintenance(BuildContext context, MaintenanceEntry entry) async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Supprimer'), content: const Text('Supprimer cette entrée de l\'historique ?'), actions: [ TextButton(onPressed: () => Navigator.pop(context, false), child: const Text('Annuler')), TextButton( onPressed: () => Navigator.pop(context, true), child: const Text('Supprimer', style: TextStyle(color: AppTheme.errorColor)), ), ], ), ); if (confirmed == true) { final repository = context.read(); await repository.deleteMaintenanceEntry(entry.id); _loadData(); } } }