/// Écran principal de Plotting et d'analyse - Interface centrale de traitement des cibles.
///
/// Affiche d'abord la calibration de la cible, puis l'overlay des anneaux et impacts détectés.
/// Permet le calcul des scores et statistiques de groupement (Plotting).
library;

import 'dart:io';
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../../core/constants/app_constants.dart';
import '../../core/theme/app_theme.dart';
import '../../data/models/target_type.dart';
import '../../data/models/shot.dart';
import '../../data/repositories/session_repository.dart';
import '../../services/target_detection_service.dart';
import '../../services/score_calculator_service.dart';
import '../../services/grouping_analyzer_service.dart';
import '../session/session_provider.dart';
import 'analysis_provider.dart';
import '../crop/crop_screen.dart';
import '../capture/capture_screen.dart';
import 'widgets/target_overlay.dart';
import 'widgets/target_calibration.dart';
import 'widgets/score_card.dart';
import 'widgets/grouping_stats.dart';

class AnalysisScreen extends StatelessWidget {
  final String imagePath;
  final TargetType targetType;
  final double? initialCenterX;
  final double? initialCenterY;
  final double? cropScale;
  final Offset? cropOffset;
  final double? cropRotation; // Reçu proprement depuis le CropScreen

  const AnalysisScreen({
    super.key,
    required this.imagePath,
    required this.targetType,
    this.initialCenterX,
    this.initialCenterY,
    this.cropScale,
    this.cropOffset,
    this.cropRotation,
  });

  @override
  Widget build(BuildContext context) {
    // Reconstitution de l'Offset pour le traitement métier en arrière-plan
    final manualCenterOffset =
    (initialCenterX != null && initialCenterY != null)
        ? Offset(initialCenterX!, initialCenterY!)
        : null;

    return ChangeNotifierProvider(
      create: (context) {
        final p = AnalysisProvider(
          detectionService: context.read<TargetDetectionService>(),
          scoreCalculatorService: context.read<ScoreCalculatorService>(),
          groupingAnalyzerService: context.read<GroupingAnalyzerService>(),
          sessionRepository: context.read<SessionRepository>(),
        );
        // Sauvegarde de l'angle de rotation d'origine directement dans l'état global
        if (cropRotation != null) {
          p.setCropRotation(cropRotation!);
        }
        p.analyzeImage(
          imagePath,
          targetType,
          autoAnalyze: false,
          manualCenter: manualCenterOffset,
        );
        return p;
      },
      child: _AnalysisScreenContent(
        cropScale: cropScale,
        cropOffset: cropOffset,
        cropRotation: cropRotation, // Envoyé à la structure d'affichage
      ),
    );
  }
}

class _AnalysisScreenContent extends StatefulWidget {
  final double? cropScale;
  final Offset? cropOffset;
  final double? cropRotation;

  const _AnalysisScreenContent({
    this.cropScale,
    this.cropOffset,
    this.cropRotation,
  });

  @override
  State<_AnalysisScreenContent> createState() => _AnalysisScreenContentState();
}

class _AnalysisScreenContentState extends State<_AnalysisScreenContent> {
  final GlobalKey<TargetCalibrationState> _calibrationKey =
  GlobalKey<TargetCalibrationState>();

  // Forcé à TRUE pour démarrer sur l'ajustement des cercles
  bool _isCalibrating = true;
  bool _isSelectingReferences = false;
  bool _isAtBottom = false;

  final ScrollController _scrollController = ScrollController();
  final TransformationController _transformationController =
  TransformationController();
  final GlobalKey _imageKey = GlobalKey();
  double _currentZoomScale = 1.0;
  String? _movingShotId;

  @override
  void initState() {
    super.initState();
    _transformationController.addListener(_onTransformChanged);
    _scrollController.addListener(_onScroll);
  }

  void _onScroll() {
    if (!_scrollController.hasClients) return;
    final isBottom =
        _scrollController.position.pixels >=
            _scrollController.position.maxScrollExtent - 20;
    if (isBottom != _isAtBottom) {
      setState(() {
        _isAtBottom = isBottom;
      });
    }
  }

  @override
  void dispose() {
    _transformationController.removeListener(_onTransformChanged);
    _transformationController.dispose();
    _scrollController.removeListener(_onScroll);
    _scrollController.dispose();
    super.dispose();
  }

  void _onTransformChanged() {
    final scale = _transformationController.value.getMaxScaleOnAxis();
    if (scale != _currentZoomScale) {
      setState(() {
        _currentZoomScale = scale;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    final provider = context.watch<AnalysisProvider>();
    final sessionProvider = context.watch<SessionProvider>();
    final targetNumber = sessionProvider.isSessionActive
        ? sessionProvider.targetCount + 1
        : null;

    final titlePrefix = _isCalibrating ? 'Calibration' : 'Plotting';
    final title = targetNumber != null
        ? '$titlePrefix - Cible $targetNumber'
        : (_isCalibrating ? 'Calibration' : 'Plotting du Tir');

    return Scaffold(
      appBar: AppBar(
        title: Text(title),
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () {
            if (_isCalibrating) {
              final provider = context.read<AnalysisProvider>();
              Navigator.pushReplacement(
                context,
                MaterialPageRoute(
                  builder: (context) => CropScreen(
                    imagePath: provider.imagePath!,
                    targetType: provider.targetType!,
                    initialScale: widget.cropScale,
                    initialOffset: widget.cropOffset,
                  ),
                ),
              );
            } else {
              setState(() => _isCalibrating = true);
            }
          },
        ),
        actions: [
          if (!_isCalibrating && !_isSelectingReferences)
            IconButton(
              icon: const Icon(Icons.refresh),
              onPressed: () => provider.analyzeImage(
                context.read<AnalysisProvider>().imagePath!,
                context.read<AnalysisProvider>().targetType!,
              ),
            ),
          if (_isCalibrating)
            TextButton(
              onPressed: () {
                // On fige la calibration courante dans le provider AVANT de
                // basculer en Plotting, pour que l'instance Plotting parte
                // d'un état figé et indépendant des rebuilds de calibration.
                _calibrationKey.currentState?.commitCalibration();
                setState(() {
                  _isCalibrating = false;
                  _isSelectingReferences = false;
                });
              },
              child: const Text(
                'TERMINER',
                style: TextStyle(
                  color: Colors.white,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
        ],
      ),
      body: Stack(
        children: [
          SingleChildScrollView(
            controller: _scrollController,
            child: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(AppConstants.defaultPadding),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      if (provider.state == AnalysisState.loading)
                        const Center(
                          child: Padding(
                            padding: EdgeInsets.symmetric(vertical: 8.0),
                            child: CircularProgressIndicator(),
                          ),
                        ),
                    ],
                  ),
                ),

                AspectRatio(
                  aspectRatio: provider.imageAspectRatio,
                  child: _isCalibrating
                      ? Stack(
                    fit: StackFit.expand,
                    children: [
                      ClipRect(
                        child: Builder(
                          builder: (context) {
                            return Transform(
                              transform: Matrix4.identity()
                                ..setTranslationRaw(
                                  widget.cropOffset?.dx ?? 0.0,
                                  widget.cropOffset?.dy ?? 0.0,
                                  0.0,
                                )
                                ..scale(1.0, 1.0)
                                ..rotateZ(
                                  (provider.cropRotation) *
                                      (math.pi / 180),
                                ),
                              alignment: Alignment.center,
                              child: Image.file(
                                File(provider.imagePath!),
                                fit: BoxFit.contain,
                              ),
                            );
                          },
                        ),
                      ),
                      TargetCalibration(
                        key: _calibrationKey,
                        initialCenterX: provider.targetCenterX,
                        initialCenterY: provider.targetCenterY,
                        initialRadius: provider.targetRadius,
                        initialInnerRadius: provider.targetInnerRadius,
                        initialRingCount: provider.ringCount,
                        initialRingRadii: provider.ringRadii,
                        targetType: provider.targetType!,
                        onCalibrationChanged:
                            (
                            centerX,
                            centerY,
                            innerRadius,
                            radius,
                            ringCount, {
                          ringRadii,
                        }) {
                          provider.adjustTargetPosition(
                            centerX,
                            centerY,
                            innerRadius,
                            radius,
                            ringCount: ringCount,
                            ringRadii: ringRadii,
                            zoomScale: 1.0,
                          );
                        },
                      ),
                    ],
                  )
                      : _buildZoomableImageWithOverlay(context, provider),
                ),

                if (!_isCalibrating)
                  Padding(
                    padding: const EdgeInsets.all(AppConstants.defaultPadding),
                    child: Column(
                      children: [
                        Card(
                          color: AppTheme.primaryColor.withValues(alpha: 0.1),
                          child: ListTile(
                            leading: const Icon(
                              Icons.tune,
                              color: AppTheme.primaryColor,
                            ),
                            title: const Text('Ajuster la calibration'),
                            subtitle: const Text(
                              'Modifier le centre ou le rayon global',
                            ),
                            trailing: const Icon(
                              Icons.arrow_forward_ios,
                              size: 16,
                            ),
                            onTap: () => setState(() => _isCalibrating = true),
                          ),
                        ),
                        const SizedBox(height: 12),
                        ScoreCard(
                          totalScore: provider.totalScore,
                          shotCount: provider.shotCount,
                          scoreResult: provider.scoreResult,
                          targetType: provider.targetType!,
                        ),
                        const SizedBox(height: 12),
                        if (provider.groupingResult != null &&
                            provider.shotCount > 1)
                          GroupingStats(
                            groupingResult: provider.groupingResult!,
                            targetCenterX: provider.targetCenterX,
                            targetCenterY: provider.targetCenterY,
                          ),
                        const SizedBox(height: 12),
                        _buildActionButtons(context, provider),
                        const SizedBox(height: 50),
                      ],
                    ),
                  )
                else
                  Padding(
                    padding: const EdgeInsets.all(AppConstants.defaultPadding),
                    child: Column(
                      children: [
                        const Text(
                          'Ajustement precis (pixel par pixel)',
                          style: TextStyle(
                            fontSize: 13,
                            fontWeight: FontWeight.w600,
                            color: Colors.white70,
                          ),
                        ),
                        const SizedBox(height: 8),
                        Center(
                          child: Builder(
                            builder: (context) {
                              final size = MediaQuery.of(context).size;
                              return _calibrationKey.currentState
                                  ?.buildDirectionalControls(
                                context,
                                size,
                              ) ??
                                  const SizedBox.shrink();
                            },
                          ),
                        ),
                        const SizedBox(height: 16),
                        Card(
                          child: Padding(
                            padding: const EdgeInsets.all(16),
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                const Text(
                                  'Instructions de calibration',
                                  style: TextStyle(
                                    fontWeight: FontWeight.bold,
                                    fontSize: 16,
                                  ),
                                ),
                                const SizedBox(height: 12),
                                _buildInstructionItem(
                                  Icons.open_with,
                                  'Glissez le centre pour positionner le centre de la cible',
                                ),
                                _buildInstructionItem(
                                  Icons.zoom_out_map,
                                  'Pincez l\'ecran a 2 doigts ou utilisez la jauge pour la taille',
                                ),
                                _buildInstructionItem(
                                  Icons.visibility,
                                  'Appuyez sur TERMINER en haut a droite pour valider',
                                ),
                                const SizedBox(height: 16),
                                Row(
                                  children: [
                                    const Text('Centre: '),
                                    Text(
                                      '(${(provider.targetCenterX * 100).toStringAsFixed(1)}%, ${(provider.targetCenterY * 100).toStringAsFixed(1)}%)',
                                      style: const TextStyle(
                                        fontWeight: FontWeight.bold,
                                      ),
                                    ),
                                  ],
                                ),
                                Row(
                                  children: [
                                    const Text('Rayon: '),
                                    Text(
                                      '${(provider.targetRadius * 100).toStringAsFixed(1)}%',
                                      style: const TextStyle(
                                        fontWeight: FontWeight.bold,
                                      ),
                                    ),
                                  ],
                                ),
                              ],
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
              ],
            ),
          ),
          Positioned(
            bottom: 0,
            left: 0,
            right: 0,
            child: Align(
              alignment: _isAtBottom
                  ? Alignment.bottomCenter
                  : Alignment.bottomRight,
              child: Padding(
                padding: _isAtBottom
                    ? EdgeInsets.zero
                    : const EdgeInsets.all(16.0),
                child: _isCalibrating
                    ? const SizedBox.shrink()
                    : FloatingActionButton.extended(
                  onPressed: () =>
                      _showSaveSessionDialog(context, provider),
                  backgroundColor: AppTheme.primaryColor,
                  icon: const Icon(Icons.save),
                  label: const Text('TERMINER LA SESSION'),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildInstructionItem(IconData icon, String text) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 8),
      child: Row(
        children: [
          Icon(icon, size: 16, color: AppTheme.primaryColor),
          const SizedBox(width: 8),
          Expanded(child: Text(text, style: const TextStyle(fontSize: 13))),
        ],
      ),
    );
  }

  Widget _buildZoomableImageWithOverlay(
      BuildContext context,
      AnalysisProvider provider,
      ) {
    return InteractiveViewer(
      transformationController: _transformationController,
      minScale: 1.0,
      maxScale: 10.0,
      boundaryMargin: const EdgeInsets.all(double.infinity),
      panEnabled: _movingShotId == null,
      child: Transform(
        transform: Matrix4.identity()
          ..setTranslationRaw(
            widget.cropOffset?.dx ?? 0.0,
            widget.cropOffset?.dy ?? 0.0,
            0.0,
          )
          ..scale(1.0, 1.0)
          ..rotateZ((provider.cropRotation) * (math.pi / 180)),
        alignment: Alignment.center,
        child: GestureDetector(
          onDoubleTapDown: (TapDownDetails details) {
            final RenderBox? box =
            _imageKey.currentContext?.findRenderObject() as RenderBox?;
            if (box == null) return;

            final localOffset = box.globalToLocal(details.globalPosition);
            final relX = localOffset.dx / box.size.width;
            final relY = localOffset.dy / box.size.height;

            if (provider.shots.isEmpty) return;

            Shot? closestShot;
            double minDistance = double.infinity;
            const double clickTolerance = 0.05;

            for (final shot in provider.shots) {
              final dx = shot.x - relX;
              final dy = shot.y - relY;
              final distance = math.sqrt(dx * dx + dy * dy);

              if (distance < minDistance && distance < clickTolerance) {
                minDistance = distance;
                closestShot = shot;
              }
            }

            if (closestShot != null) {
              _showShotDetails(context, provider, closestShot);
            }
          },
          onLongPressStart: (LongPressStartDetails details) {
            final RenderBox? box =
            _imageKey.currentContext?.findRenderObject() as RenderBox?;
            if (box == null) return;

            final localOffset = box.globalToLocal(details.globalPosition);
            final relX = localOffset.dx / box.size.width;
            final relY = localOffset.dy / box.size.height;

            if (provider.shots.isEmpty) return;

            Shot? closestShot;
            double minDistance = double.infinity;
            const double dragTolerance = 0.06;

            for (final shot in provider.shots) {
              final dx = shot.x - relX;
              final dy = shot.y - relY;
              final distance = math.sqrt(dx * dx + dy * dy);

              if (distance < minDistance && distance < dragTolerance) {
                minDistance = distance;
                closestShot = shot;
              }
            }

            if (closestShot != null) {
              setState(() {
                _movingShotId = closestShot!.id;
              });
            }
          },
          onLongPressMoveUpdate: (LongPressMoveUpdateDetails details) {
            if (_movingShotId == null) return;

            final RenderBox? box =
            _imageKey.currentContext?.findRenderObject() as RenderBox?;
            if (box == null) return;

            final adjustedGlobalPosition =
                details.globalPosition + const Offset(-25, -35);
            final localOffset = box.globalToLocal(adjustedGlobalPosition);

            final relX = (localOffset.dx / box.size.width).clamp(0.0, 1.0);
            final relY = (localOffset.dy / box.size.height).clamp(0.0, 1.0);

            provider.updateShotPosition(_movingShotId!, relX, relY);
          },
          onLongPressEnd: (_) {
            if (_movingShotId != null) {
              setState(() {
                _movingShotId = null;
              });
            }
          },
          child: Stack(
            children: [
              Image.file(
                File(provider.imagePath!),
                key: _imageKey,
                fit: BoxFit.contain,
              ),
              TargetOverlay(
                targetCenterX: provider.targetCenterX,
                targetCenterY: provider.targetCenterY,
                targetRadius: provider.targetRadius,
                targetType: provider.targetType!,
                shots: provider.shots,
                showRings: true,
                zoomScale: _currentZoomScale,
                onShotTapped: (shot) =>
                    _showShotDetails(context, provider, shot),
                onAddShot: (relX, relY) => provider.addShot(relX, relY),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildActionButtons(BuildContext context, AnalysisProvider provider) {
    return const Column(children: [Row(children: [])]);
  }

  void _showShotDetails(
      BuildContext context,
      AnalysisProvider provider,
      Shot shot,
      ) {
    showModalBottomSheet(
      context: context,
      builder: (context) => Container(
        padding: const EdgeInsets.all(24),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(
              'Impact #${provider.shots.indexOf(shot) + 1}',
              style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
            ),
            Text(
              'ID: ${shot.id}',
              style: Theme.of(
                context,
              ).textTheme.bodySmall?.copyWith(color: Colors.grey, fontSize: 10),
            ),
            const SizedBox(height: 16),
            ListTile(
              leading: const Icon(Icons.score),
              title: const Text('Modifier le score'),
              trailing: DropdownButton<int>(
                value: shot.score.clamp(0, 10),
                items: List.generate(11, (index) => index)
                    .map(
                      (s) => DropdownMenuItem(
                    value: s,
                    child: Text(
                      '$s',
                      style: const TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 18,
                      ),
                    ),
                  ),
                )
                    .toList(),
                onChanged: (newScore) {
                  if (newScore != null) {
                    provider.updateShotScore(shot.id, newScore);
                    Navigator.pop(context);
                  }
                },
              ),
            ),
            const SizedBox(height: 24),
            Row(
              children: [
                Expanded(
                  child: OutlinedButton.icon(
                    onPressed: () {
                      provider.removeShot(shot.id);
                      Navigator.pop(context);
                    },
                    icon: const Icon(Icons.delete, color: Colors.red),
                    label: const Text(
                      'SUPPRIMER',
                      style: TextStyle(color: Colors.red),
                    ),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  void _showSaveSessionDialog(BuildContext context, AnalysisProvider provider) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Session Terminee'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('Nombre de tirs: ${provider.shotCount}'),
            Text('Score total: ${provider.totalScore}'),
            const SizedBox(height: 16),
            const Text('Voulez-vous enregistrer cette session ?'),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () {
              Navigator.pop(context);
              final path = provider.imagePath!;
              final type = provider.targetType!;

              Navigator.pushReplacement(
                context,
                MaterialPageRoute(
                  builder: (context) => CropScreen(
                    imagePath: path,
                    targetType: type,
                    initialScale: widget.cropScale,
                    initialOffset: widget.cropOffset,
                  ),
                ),
              );
            },
            child: const Text('ANNULER'),
          ),
          ElevatedButton(
            onPressed: () async {
              try {
                final sessionProvider = context.read<SessionProvider>();
                final analysis = await provider.saveSession(
                  sessionId: sessionProvider.activeSessionId,
                  weaponName: sessionProvider.currentWeapon,
                  weaponId: sessionProvider.currentWeaponId,
                  distance: sessionProvider.distance,
                  date: sessionProvider.sessionDate,
                );

                sessionProvider.addAnalysis(analysis);

                if (context.mounted) {
                  Navigator.pop(context);
                  Navigator.pushAndRemoveUntil(
                    context,
                    MaterialPageRoute(
                      builder: (context) => const CaptureScreen(),
                    ),
                        (route) => route.isFirst,
                  );
                }
              } catch (e) {
                if (context.mounted) {
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(
                      content: Text('Erreur: $e'),
                      backgroundColor: AppTheme.errorColor,
                    ),
                  );
                }
              }
            },
            child: const Text('AJOUTER UNE CIBLE'),
          ),
          ElevatedButton(
            onPressed: () async {
              try {
                final sessionProvider = context.read<SessionProvider>();
                await provider.saveSession(
                  sessionId: sessionProvider.activeSessionId,
                  weaponName: sessionProvider.currentWeapon,
                  weaponId: sessionProvider.currentWeaponId,
                  distance: sessionProvider.distance,
                  date: sessionProvider.sessionDate,
                );

                if (context.mounted) {
                  sessionProvider.endSession();
                  Navigator.pop(context);
                  Navigator.of(context).popUntil((route) => route.isFirst);
                }
              } catch (e) {
                if (context.mounted) {
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(
                      content: Text('Erreur: $e'),
                      backgroundColor: AppTheme.errorColor,
                    ),
                  );
                }
              }
            },
            child: const Text('TERMINER TOUT'),
          ),
        ],
      ),
    );
  }
}