import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:slrpg_app/l10n/app_localizations.dart';

import '../../../../core/theme/app_theme.dart';
import '../../../../shared/data/local/app_database.dart';
import '../../../../shared/data/repositories/cycle_repository.dart';
import '../../../../shared/data/repositories/user_repository.dart';
import '../../../../shared/data/repositories/workout_repository.dart';
import '../../../../shared/domain/entities/exercise.dart';
import '../../../../shared/domain/logic/wendler_calculator.dart';
import '../../domain/entities/stats_data_point.dart';
import '../widgets/progress_chart.dart';

class StatsScreen extends ConsumerStatefulWidget {
  const StatsScreen({super.key});

  @override
  ConsumerState<StatsScreen> createState() => _StatsScreenState();
}

class _StatsScreenState extends ConsumerState<StatsScreen> {
  bool _isLoading = false;

  String _selectedExercise = 'squat';
  String _selectedRange = '3m'; // 1m, 3m, 1y, all
  List<StatsDataPoint> _chartData = [];
  bool _isChartLoading = true;

  @override
  void initState() {
    super.initState();
    _loadStats();
  }

  Future<void> _loadStats() async {
    setState(() => _isChartLoading = true);

    try {
      final workoutRepo = ref.read(workoutRepositoryProvider);
      final userRepo = ref.read(userRepositoryProvider);

      final user = await userRepo.getLocalUser();
      if (user == null) {
        setState(() => _isChartLoading = false);
        return;
      }
      final userId = user.serverId ?? user.id.toString();
      final allWorkouts = await workoutRepo.getCompletedWorkouts(userId);

      final points = <StatsDataPoint>[];

      for (var workout in allWorkouts) {
        if (workout.completedAt == null) continue;

        final exercisesList = workout.exercises;

        double max1RM = 0.0;
        double sessionVolume = 0.0;
        bool foundExercise = false;
        double trainingMax = 0.0;

        for (var exDynamic in exercisesList) {
          final exJson = exDynamic as Map<String, dynamic>;
          final exercise = Exercise.fromJson(exJson);

          if (exercise.exerciseId == _selectedExercise) {
            foundExercise = true;

            for (var set in exercise.sets) {
              if (!set.completed || set.repsActual <= 0) continue;

              sessionVolume += set.targetWeightTotal * set.repsActual;

              final e1rm = WendlerCalculator.calculate1RM(
                  set.targetWeightTotal, set.repsActual);

              if (e1rm > max1RM) {
                max1RM = e1rm;
              }

              if (set.targetPercentage > 0 && trainingMax == 0) {
                trainingMax =
                    set.targetWeightTotal / (set.targetPercentage / 100.0);
              }
            }
          }
        }

        if (foundExercise && max1RM > 0) {
          points.add(StatsDataPoint(
            date: workout.completedAt!,
            trainingMax: trainingMax,
            estimated1RM: max1RM,
            totalVolume: sessionVolume,
          ));
        }
      }

      points.sort((a, b) => a.date.compareTo(b.date));

      final now = DateTime.now();
      final filteredPoints = points.where((p) {
        if (_selectedRange == '1m') {
          return p.date.isAfter(now.subtract(const Duration(days: 30)));
        } else if (_selectedRange == '3m') {
          return p.date.isAfter(now.subtract(const Duration(days: 90)));
        } else if (_selectedRange == '1y') {
          return p.date.isAfter(now.subtract(const Duration(days: 365)));
        }
        return true;
      }).toList();

      if (mounted) {
        setState(() {
          _chartData = filteredPoints;
          _isChartLoading = false;
        });
      }
    } catch (e) {
      log('Failed to calculate local stats: $e');
      if (mounted) {
        setState(() {
          _chartData = [];
          _isChartLoading = false;
        });
      }
    }
  }

  void _onFilterChanged(String exercise, String range) {
    setState(() {
      _selectedExercise = exercise;
      _selectedRange = range;
    });
    _loadStats();
  }

  Future<void> _handleFinishCycle(CycleCollection currentCycle) async {
    setState(() => _isLoading = true);
    try {
      final cycleRepo = ref.read(cycleRepositoryProvider);

      final oldTMs = currentCycle.trainingMaxes;

      final newCycle = await cycleRepo.finishCycle();
      final newTMs = newCycle.trainingMaxes;

      if (mounted) {
        await showDialog(
          context: context,
          barrierDismissible: false,
          builder: (context) => _CycleFinishDialog(
            oldTMs: oldTMs,
            newTMs: newTMs,
            newCycleNumber: newCycle.cycleNumber,
          ),
        );

        setState(() {});
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
              content: Text('Error finishing cycle: $e'),
              backgroundColor: AppTheme.errorColor),
        );
      }
    } finally {
      if (mounted) setState(() => _isLoading = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    final cycleRepo = ref.watch(cycleRepositoryProvider);
    final userRepo = ref.watch(userRepositoryProvider);
    final l10n = AppLocalizations.of(context)!;

    return Scaffold(
      appBar: AppBar(
        title: Text(l10n.statsTitle),
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () => context.go('/hub'),
        ),
      ),
      body: FutureBuilder<List<dynamic>>(
        future: Future.wait([
          cycleRepo.getCurrentCycle(),
          userRepo.getLocalUser(),
        ]),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          }

          final currentCycle = snapshot.data?[0] as CycleCollection?;
          final user = snapshot.data?[1] as UserCollection;
          final variants = user.exerciseVariants ?? {};
          final pullVariant = variants['pull'] ?? 'pullup';
          final pushVariant = variants['push'] ?? 'dip';

          String getLabel(String id) {
            switch (id) {
              case 'squat':
                return l10n.exerciseSquat;
              case 'pullup':
                return l10n.exercisePullup;
              case 'row':
                return l10n.exerciseRow;
              case 'dip':
                return l10n.exerciseDip;
              case 'bench':
                return l10n.exerciseBench;
              default:
                return id;
            }
          }

          return SingleChildScrollView(
            padding: const EdgeInsets.all(16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                if (currentCycle != null) ...[
                  _CurrentCycleCard(
                    cycle: currentCycle,
                    user: user,
                    onFinish: _isLoading
                        ? null
                        : () => _handleFinishCycle(currentCycle),
                  ),
                  const SizedBox(height: 24),
                ],
                Text(
                  l10n.statsProgressAnalysis,
                  style: Theme.of(context)
                      .textTheme
                      .titleLarge
                      ?.copyWith(color: AppTheme.textPrimary),
                ),
                const SizedBox(height: 16),
                SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: Row(
                    children: [
                      _FilterChip(
                        label: l10n.exerciseSquat,
                        isSelected: _selectedExercise == 'squat',
                        onTap: () => _onFilterChanged('squat', _selectedRange),
                      ),
                      const SizedBox(width: 8),
                      _FilterChip(
                        label: getLabel(pullVariant),
                        isSelected: _selectedExercise == pullVariant,
                        onTap: () =>
                            _onFilterChanged(pullVariant, _selectedRange),
                      ),
                      const SizedBox(width: 8),
                      _FilterChip(
                        label: getLabel(pushVariant),
                        isSelected: _selectedExercise == pushVariant,
                        onTap: () =>
                            _onFilterChanged(pushVariant, _selectedRange),
                      ),
                    ],
                  ),
                ),
                const SizedBox(height: 16),
                _isChartLoading
                    ? const SizedBox(
                        height: 250,
                        child: Center(child: CircularProgressIndicator()))
                    : ProgressChart(data: _chartData),
              ],
            ),
          );
        },
      ),
    );
  }
}

class _CurrentCycleCard extends StatelessWidget {
  final CycleCollection cycle;
  final UserCollection user;
  final VoidCallback? onFinish;

  const _CurrentCycleCard(
      {required this.cycle, required this.user, required this.onFinish});

  @override
  Widget build(BuildContext context) {
    final tms = cycle.trainingMaxes;
    final variants = user.exerciseVariants ?? {};
    final pullVariant = variants['pull'] ?? 'pullup';
    final pushVariant = variants['push'] ?? 'dip';
    final l10n = AppLocalizations.of(context)!;

    String getLabel(String id) {
      switch (id) {
        case 'squat':
          return l10n.exerciseSquat;
        case 'pullup':
          return l10n.exercisePullup;
        case 'row':
          return l10n.exerciseRow;
        case 'dip':
          return l10n.exerciseDip;
        case 'bench':
          return l10n.exerciseBench;
        default:
          return id;
      }
    }

    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text(
                  l10n.statsCycleTitle(cycle.cycleNumber),
                  style: Theme.of(context).textTheme.headlineMedium?.copyWith(
                        color: AppTheme.primaryColor,
                        fontSize: 24,
                      ),
                ),
                Container(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                  decoration: BoxDecoration(
                    color: AppTheme.successColor.withValues(alpha: 0.2),
                    borderRadius: BorderRadius.circular(4),
                  ),
                  child: Text(
                    l10n.hubActiveYes,
                    style: TextStyle(
                        color: AppTheme.successColor,
                        fontWeight: FontWeight.bold,
                        fontSize: 12),
                  ),
                ),
              ],
            ),
            const Divider(height: 32),
            Text(l10n.statsCurrentTM,
                style: Theme.of(context).textTheme.labelLarge),
            const SizedBox(height: 16),
            _StatRow(
                label: l10n.exerciseSquat,
                value: '${tms['squat'].toStringAsFixed(2)} ${l10n.unitKg}'),
            _StatRow(
                label: getLabel(pullVariant),
                value: '${tms['pullup'].toStringAsFixed(2)} ${l10n.unitKg}'),
            _StatRow(
                label: getLabel(pushVariant),
                value: '${tms['dip'].toStringAsFixed(2)} ${l10n.unitKg}'),
            const SizedBox(height: 32),
            SizedBox(
              width: double.infinity,
              child: ElevatedButton.icon(
                onPressed: onFinish,
                icon: const Icon(Icons.upgrade),
                label: Text(l10n.statsFinishCycle),
                style: ElevatedButton.styleFrom(
                  backgroundColor: AppTheme.secondaryColor,
                  foregroundColor: Colors.white,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _StatRow extends StatelessWidget {
  final String label;
  final String value;

  const _StatRow({required this.label, required this.value});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 8),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(label, style: Theme.of(context).textTheme.bodyLarge),
          Text(value,
              style: Theme.of(context).textTheme.titleLarge?.copyWith(
                  fontWeight: FontWeight.bold, color: AppTheme.textSecondary)),
        ],
      ),
    );
  }
}

class _CycleFinishDialog extends StatelessWidget {
  final Map<String, dynamic> oldTMs;
  final Map<String, dynamic> newTMs;
  final int newCycleNumber;

  const _CycleFinishDialog({
    required this.oldTMs,
    required this.newTMs,
    required this.newCycleNumber,
  });

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;
    return AlertDialog(
      title: Text(l10n.statsCycleFinishedTitle),
      content: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            l10n.statsCycleFinishedBody,
          ),
          const SizedBox(height: 16),
          const Divider(),
          const SizedBox(height: 8),
          Text(l10n.statsTMIncreased,
              style: TextStyle(fontWeight: FontWeight.bold)),
          const SizedBox(height: 16),
          _DiffRow(
              name: l10n.exerciseSquat,
              oldVal: (oldTMs['squat'] as num).toDouble(),
              newVal: (newTMs['squat'] as num).toDouble()),
          _DiffRow(
              name: l10n.exercisePullup,
              oldVal: (oldTMs['pullup'] as num).toDouble(),
              newVal: (newTMs['pullup'] as num).toDouble()),
          _DiffRow(
              name: l10n.exerciseDip,
              oldVal: (oldTMs['dip'] as num).toDouble(),
              newVal: (newTMs['dip'] as num).toDouble()),
        ],
      ),
      actions: [
        ElevatedButton(
          onPressed: () => Navigator.of(context).pop(),
          child: Text(l10n.statsEnterNextLevel),
        ),
      ],
    );
  }
}

class _DiffRow extends StatelessWidget {
  final String name;
  final double oldVal;
  final double newVal;

  const _DiffRow(
      {required this.name, required this.oldVal, required this.newVal});

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;
    final diff = newVal - oldVal;
    final isPositive = diff > 0;

    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4),
      child: Row(
        children: [
          Expanded(child: Text(name)),
          Text('${oldVal.toStringAsFixed(2)} → ',
              style: const TextStyle(color: Colors.grey)),
          Text(
            newVal.toStringAsFixed(2),
            style: const TextStyle(fontWeight: FontWeight.bold),
          ),
          const SizedBox(width: 8),
          if (isPositive)
            Text('+${diff.toStringAsFixed(2)}',
                style: const TextStyle(
                    color: AppTheme.successColor, fontWeight: FontWeight.bold))
          else
            Text(l10n.statsStalled,
                style: const TextStyle(
                    color: AppTheme.secondaryColor, fontSize: 12)),
        ],
      ),
    );
  }
}

class _FilterChip extends StatelessWidget {
  final String label;
  final bool isSelected;
  final VoidCallback onTap;

  const _FilterChip(
      {required this.label, required this.isSelected, required this.onTap});

  @override
  Widget build(BuildContext context) {
    return ChoiceChip(
      label: Text(label),
      selected: isSelected,
      onSelected: (_) => onTap(),
      selectedColor: AppTheme.primaryColor.withValues(alpha: 0.2),
      labelStyle: TextStyle(
        color: isSelected ? AppTheme.primaryColor : Colors.grey,
        fontWeight: FontWeight.bold,
      ),
      side: BorderSide(
        color: isSelected
            ? AppTheme.primaryColor
            : Colors.grey.withValues(alpha: 0.3),
      ),
    );
  }
}
