import 'dart:io'; 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/session.dart'; import '../../data/models/target_analysis.dart'; import '../../data/models/target_type.dart'; import '../../data/repositories/session_repository.dart'; import '../../services/score_calculator_service.dart'; import '../../services/grouping_analyzer_service.dart'; import '../analysis/widgets/target_overlay.dart'; import '../analysis/widgets/score_card.dart'; import '../analysis/widgets/grouping_stats.dart'; import '../statistics/statistics_screen.dart'; class SessionDetailScreen extends StatefulWidget { final Session session; const SessionDetailScreen({ super.key, required this.session, }); @override State createState() => _SessionDetailScreenState(); } class _SessionDetailScreenState extends State { int _currentTargetIndex = 0; @override Widget build(BuildContext context) { final scoreCalculator = context.read(); final groupingAnalyzer = context.read(); final currentAnalysis = widget.session.analyses[_currentTargetIndex]; final scoreResult = scoreCalculator.calculateScores( shots: currentAnalysis.shots, targetType: currentAnalysis.targetType, targetCenterX: currentAnalysis.targetCenterX ?? 0.5, targetCenterY: currentAnalysis.targetCenterY ?? 0.5, targetRadius: currentAnalysis.targetRadius ?? 0.4, ); final groupingResult = groupingAnalyzer.analyzeGrouping(currentAnalysis.shots); return Scaffold( appBar: AppBar( title: Text(widget.session.weapon), actions: [ IconButton( icon: const Icon(Icons.analytics), onPressed: () => Navigator.push( context, MaterialPageRoute( builder: (_) => StatisticsScreen(singleSession: widget.session), ), ), tooltip: 'Statistiques', ), IconButton( icon: const Icon(Icons.delete), onPressed: () => _confirmDelete(context), tooltip: 'Supprimer', ), ], ), body: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Weapon and session overview _buildSessionHeader(context), // Target selector if multiple targets if (widget.session.targetCount > 1) _buildTargetSelector(), // Target image with overlay AspectRatio( aspectRatio: 1, child: Stack( fit: StackFit.expand, children: [ if (File(currentAnalysis.imagePath).existsSync()) Image.file( File(currentAnalysis.imagePath), fit: BoxFit.cover, ) else Container( color: Colors.grey[200], child: const Center( child: Icon(Icons.image_not_supported, size: 64), ), ), TargetOverlay( shots: currentAnalysis.shots, targetCenterX: currentAnalysis.targetCenterX ?? 0.5, targetCenterY: currentAnalysis.targetCenterY ?? 0.5, targetRadius: currentAnalysis.targetRadius ?? 0.4, targetType: currentAnalysis.targetType, groupingCenterX: currentAnalysis.groupingCenterX, groupingCenterY: currentAnalysis.groupingCenterY, groupingDiameter: currentAnalysis.groupingDiameter, ), ], ), ), Padding( padding: const EdgeInsets.all(AppConstants.defaultPadding), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Analysis Info _buildAnalysisInfo(context, currentAnalysis), const SizedBox(height: 12), // Score card for current target ScoreCard( totalScore: currentAnalysis.totalScore, shotCount: currentAnalysis.shotCount, scoreResult: scoreResult, targetType: currentAnalysis.targetType, ), const SizedBox(height: 12), // Grouping stats for current target if (currentAnalysis.shotCount > 1) GroupingStats( groupingResult: groupingResult, targetCenterX: currentAnalysis.targetCenterX ?? 0.5, targetCenterY: currentAnalysis.targetCenterY ?? 0.5, ), // Notes for current target if (currentAnalysis.notes != null && currentAnalysis.notes!.isNotEmpty) ...[ const SizedBox(height: 12), _buildNotesCard(context, currentAnalysis.notes!), ], // Session notes if (widget.session.notes != null && widget.session.notes!.isNotEmpty) ...[ const SizedBox(height: 12), _buildNotesCard(context, widget.session.notes!, title: 'Notes de session'), ], ], ), ), ], ), ), ); } Widget _buildSessionHeader(BuildContext context) { return Container( padding: const EdgeInsets.all(16), color: AppTheme.primaryColor.withValues(alpha: 0.1), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( DateFormat('EEEE dd MMMM yyyy', 'fr_FR').format(widget.session.createdAt), style: const TextStyle(fontWeight: FontWeight.bold), ), Text( DateFormat('HH:mm').format(widget.session.createdAt), style: Theme.of(context).textTheme.bodySmall, ), ], ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( 'Score Total: ${widget.session.totalScore}', style: const TextStyle(fontWeight: FontWeight.bold, color: AppTheme.primaryColor), ), Text( '${widget.session.totalShots} tirs au total', style: Theme.of(context).textTheme.bodySmall, ), ], ), ], ), ], ), ); } Widget _buildTargetSelector() { return Container( height: 50, margin: const EdgeInsets.symmetric(vertical: 8), child: ListView.builder( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: widget.session.targetCount, itemBuilder: (context, index) { final isSelected = _currentTargetIndex == index; return Padding( padding: const EdgeInsets.only(right: 8), child: ChoiceChip( label: Text('Cible ${index + 1}'), selected: isSelected, onSelected: (selected) { if (selected) { setState(() => _currentTargetIndex = index); } }, ), ); }, ), ); } Widget _buildAnalysisInfo(BuildContext context, TargetAnalysis analysis) { return Card( child: Padding( padding: const EdgeInsets.all(12), child: Row( children: [ Icon( analysis.targetType == TargetType.concentric ? Icons.track_changes : Icons.person, color: AppTheme.primaryColor, ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( analysis.targetType.displayName, style: const TextStyle(fontWeight: FontWeight.bold), ), Text( 'Cible ${_currentTargetIndex + 1} sur ${widget.session.targetCount}', style: Theme.of(context).textTheme.bodySmall, ), ], ), ), ], ), ), ); } Widget _buildNotesCard(BuildContext context, String notes, {String title = 'Notes'}) { return Card( child: Padding( padding: const EdgeInsets.all(AppConstants.defaultPadding), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.notes, color: AppTheme.primaryColor, size: 20), const SizedBox(width: 8), Text( title, style: const TextStyle(fontWeight: FontWeight.bold), ), ], ), const Divider(), Text(notes), ], ), ), ); } Future _confirmDelete(BuildContext context) async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Supprimer'), content: const Text('Voulez-vous vraiment supprimer cette session entière ?'), 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 && context.mounted) { try { final repository = context.read(); await repository.deleteSession(widget.session.id); if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Session supprimée')), ); Navigator.pop(context); } } catch (e) { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Erreur: $e'), backgroundColor: AppTheme.errorColor), ); } } } } }