import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../core/utils/logger.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:intl/intl.dart';
import '../../../../shared/design_system/unionflow_design_system.dart';
import '../../../../shared/design_system/tokens/unionflow_colors.dart';
import '../../../../shared/widgets/loading_widget.dart';
import '../../../../shared/widgets/error_widget.dart';
import '../../bloc/contributions_bloc.dart';
import '../../bloc/contributions_event.dart';
import '../../bloc/contributions_state.dart';
import '../../data/models/contribution_model.dart';

/// Page dédiée « Mes statistiques cotisations » : KPIs, graphiques et synthèse.
/// Données réelles via GET /api/cotisations/mes-cotisations/synthese + liste des cotisations.
class MesStatistiquesCotisationsPage extends StatefulWidget {
  const MesStatistiquesCotisationsPage({super.key});

  @override
  State<MesStatistiquesCotisationsPage> createState() => _MesStatistiquesCotisationsPageState();
}

class _MesStatistiquesCotisationsPageState extends State<MesStatistiquesCotisationsPage> {
  Map<String, dynamic>? _synthese;
  List<ContributionModel>? _cotisations;
  String? _error;
  final _currencyFormat = NumberFormat.currency(locale: 'fr_FR', symbol: 'FCFA', decimalDigits: 0);

  @override
  void initState() {
    super.initState();
    // Charge uniquement la synthèse ; la liste est conservée dans l'état pour ne pas perdre l'onglet Toutes au retour.
    context.read<ContributionsBloc>().add(const LoadContributionsStats());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: ColorTokens.background,
      appBar: UFAppBar(
        title: 'Mes statistiques cotisations',
        backgroundColor: ColorTokens.surface,
        foregroundColor: ColorTokens.onSurface,
      ),
      body: BlocListener<ContributionsBloc, ContributionsState>(
        listener: (context, state) {
          if (state is ContributionsStatsLoaded) {
            setState(() {
              _synthese = state.stats;
              _cotisations = state.contributions;
              _error = null;
            });
          }
          if (state is ContributionsLoaded) {
            setState(() {
              _cotisations = state.contributions;
              _error = null;
            });
          }
          if (state is ContributionsError) {
            setState(() => _error = state.message);
          }
        },
        child: RefreshIndicator(
          onRefresh: () async {
            context.read<ContributionsBloc>().add(const LoadContributionsStats());
          },
          child: _buildBody(),
        ),
      ),
    );
  }

  Widget _buildBody() {
    if (_error != null) {
      return Center(
        child: AppErrorWidget(
          message: _error!,
          onRetry: () {
            context.read<ContributionsBloc>().add(const LoadContributionsStats());
            context.read<ContributionsBloc>().add(const LoadContributions());
          },
        ),
      );
    }

    if (_synthese == null && _cotisations == null) {
      return const Center(child: AppLoadingWidget());
    }

    return SingleChildScrollView(
      physics: const AlwaysScrollableScrollPhysics(),
      padding: const EdgeInsets.all(20),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          _buildHeader(),
          const SizedBox(height: 24),
          _buildKpiCards(),
          const SizedBox(height: 20),
          _buildTauxSection(),
          const SizedBox(height: 20),
          if (_cotisations != null && _cotisations!.isNotEmpty) _buildRepartitionChart(),
          if (_cotisations != null && _cotisations!.isNotEmpty) const SizedBox(height: 20),
          if (_cotisations != null && _cotisations!.isNotEmpty) _buildEvolutionSection(),
          const SizedBox(height: 20),
          _buildProchainesEcheances(),
          const SizedBox(height: 32),
        ],
      ),
    );
  }

  Widget _buildHeader() {
    final annee = _synthese?['anneeEnCours'] is int
        ? _synthese!['anneeEnCours'] as int
        : DateTime.now().year;
    return Column(
      children: [
        Text(
          'Synthèse $annee',
          style: AppTypography.headerSmall.copyWith(fontSize: 20),
        ),
        const SizedBox(height: 4),
        Text(
          'Votre situation cotisations',
          style: AppTypography.bodyTextSmall.copyWith(color: ColorTokens.onSurfaceVariant),
        ),
      ],
    );
  }

  Widget _buildKpiCards() {
    final montantDu = _toDouble(_synthese?['montantDu']);
    final totalPayeAnnee = _toDouble(_synthese?['totalPayeAnnee']);
    final enAttente = _synthese?['cotisationsEnAttente'] is int
        ? _synthese!['cotisationsEnAttente'] as int
        : ((_synthese?['cotisationsEnAttente'] as num?)?.toInt() ?? 0);
    final prochaineStr = _synthese?['prochaineEcheance']?.toString();

    return Column(
      children: [
        Row(
          children: [
            Expanded(
              child: _kpiCard(
                'Montant dû',
                _currencyFormat.format(montantDu),
                icon: Icons.pending_actions_outlined,
                color: montantDu > 0 ? UnionFlowColors.terracotta : UnionFlowColors.success,
              ),
            ),
            const SizedBox(width: 12),
            Expanded(
              child: _kpiCard(
                'Payé cette année',
                _currencyFormat.format(totalPayeAnnee),
                icon: Icons.check_circle_outline,
                color: UnionFlowColors.unionGreen,
              ),
            ),
          ],
        ),
        const SizedBox(height: 12),
        Row(
          children: [
            Expanded(
              child: _kpiCard(
                'En attente',
                '$enAttente',
                icon: Icons.schedule,
                color: enAttente > 0 ? UnionFlowColors.gold : UnionFlowColors.success,
              ),
            ),
            const SizedBox(width: 12),
            Expanded(
              child: _kpiCard(
                'Prochaine échéance',
                prochaineStr != null && prochaineStr.isNotEmpty && prochaineStr != 'null'
                    ? _formatDate(prochaineStr)
                    : '—',
                icon: Icons.event,
                color: UnionFlowColors.indigo,
              ),
            ),
          ],
        ),
      ],
    );
  }

  Widget _kpiCard(String label, String value, {required IconData icon, required Color color}) {
    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: ColorTokens.surface,
        borderRadius: BorderRadius.circular(12),
        border: Border.all(color: ColorTokens.outline),
        boxShadow: [BoxShadow(color: ColorTokens.shadow.withOpacity(0.06), blurRadius: 8, offset: const Offset(0, 2))],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Icon(icon, size: 20, color: color),
              const SizedBox(width: 8),
              Expanded(
                child: Text(
                  label,
                  style: AppTypography.bodyTextSmall.copyWith(color: ColorTokens.onSurfaceVariant),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
              ),
            ],
          ),
          const SizedBox(height: 8),
          Text(
            value,
            style: AppTypography.headerSmall.copyWith(color: color, fontSize: 15),
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
          ),
        ],
      ),
    );
  }

  Widget _buildTauxSection() {
    final montantDu = _toDouble(_synthese?['montantDu']);
    final totalPayeAnnee = _toDouble(_synthese?['totalPayeAnnee']);
    final total = montantDu + totalPayeAnnee;
    final taux = total > 0 ? (totalPayeAnnee / total * 100) : 0.0;

    return Container(
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: ColorTokens.surface,
        borderRadius: BorderRadius.circular(16),
        border: Border.all(color: ColorTokens.outline),
        boxShadow: [BoxShadow(color: ColorTokens.shadow.withOpacity(0.06), blurRadius: 8, offset: const Offset(0, 2))],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            'Taux de paiement',
            style: AppTypography.bodyTextSmall.copyWith(
              fontWeight: FontWeight.w700,
              color: ColorTokens.onSurfaceVariant,
            ),
          ),
          const SizedBox(height: 12),
          ClipRRect(
            borderRadius: BorderRadius.circular(8),
            child: LinearProgressIndicator(
              value: (taux / 100).clamp(0.0, 1.0),
              minHeight: 12,
              backgroundColor: ColorTokens.onSurfaceVariant.withOpacity(0.2),
              valueColor: AlwaysStoppedAnimation<Color>(
                taux >= 75 ? UnionFlowColors.success : (taux >= 50 ? UnionFlowColors.gold : UnionFlowColors.terracotta),
              ),
            ),
          ),
          const SizedBox(height: 8),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text('0 %', style: AppTypography.bodyTextSmall.copyWith(color: ColorTokens.onSurfaceVariant)),
              Text(
                '${taux.toStringAsFixed(0)} %',
                style: AppTypography.headerSmall.copyWith(color: UnionFlowColors.unionGreen, fontWeight: FontWeight.w700),
              ),
              Text('100 %', style: AppTypography.bodyTextSmall.copyWith(color: ColorTokens.onSurfaceVariant)),
            ],
          ),
        ],
      ),
    );
  }

  Widget _buildRepartitionChart() {
    final paye = _cotisations!
        .where((c) => c.statut == ContributionStatus.payee)
        .fold<double>(0, (s, c) => s + (c.montantPaye ?? c.montant));
    final du = _cotisations!
        .where((c) => c.statut != ContributionStatus.payee && c.statut != ContributionStatus.annulee)
        .fold<double>(0, (s, c) => s + c.montant);
    if (paye + du <= 0) return const SizedBox.shrink();

    final sections = <PieChartSectionData>[];
    if (paye > 0) {
      sections.add(PieChartSectionData(
        color: UnionFlowColors.unionGreen,
        value: paye,
        title: 'Payé',
        radius: 60,
        titleStyle: const TextStyle(fontSize: 11, fontWeight: FontWeight.w600, color: Colors.white),
      ));
    }
    if (du > 0) {
      sections.add(PieChartSectionData(
        color: UnionFlowColors.terracotta,
        value: du,
        title: 'Dû',
        radius: 60,
        titleStyle: const TextStyle(fontSize: 11, fontWeight: FontWeight.w600, color: Colors.white),
      ));
    }
    if (sections.isEmpty) return const SizedBox.shrink();

    return Container(
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: ColorTokens.surface,
        borderRadius: BorderRadius.circular(16),
        border: Border.all(color: ColorTokens.outline),
        boxShadow: [BoxShadow(color: ColorTokens.shadow.withOpacity(0.06), blurRadius: 8, offset: const Offset(0, 2))],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            'Répartition Payé / Dû',
            style: AppTypography.bodyTextSmall.copyWith(
              fontWeight: FontWeight.w700,
              color: ColorTokens.onSurfaceVariant,
            ),
          ),
          const SizedBox(height: 16),
          SizedBox(
            height: 200,
            child: PieChart(
              PieChartData(
                sectionsSpace: 2,
                centerSpaceRadius: 40,
                sections: sections,
              ),
            ),
          ),
          const SizedBox(height: 16),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              _legendItem(UnionFlowColors.unionGreen, 'Payé', _currencyFormat.format(paye)),
              _legendItem(UnionFlowColors.terracotta, 'Dû', _currencyFormat.format(du)),
            ],
          ),
        ],
      ),
    );
  }

  Widget _legendItem(Color color, String label, String value) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        Container(width: 12, height: 12, decoration: BoxDecoration(color: color, shape: BoxShape.circle)),
        const SizedBox(width: 8),
        Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(label, style: AppTypography.bodyTextSmall.copyWith(color: ColorTokens.onSurfaceVariant)),
            Text(value, style: AppTypography.bodyTextSmall.copyWith(fontWeight: FontWeight.w600)),
          ],
        ),
      ],
    );
  }

  Widget _buildEvolutionSection() {
    final payees = _cotisations!.where((c) => c.statut == ContributionStatus.payee).toList();
    if (payees.isEmpty) return const SizedBox.shrink();

    final byMonth = <int, double>{};
    for (final c in payees) {
      final d = c.datePaiement ?? c.dateEcheance;
      final month = d.month + d.year * 12;
      byMonth[month] = (byMonth[month] ?? 0) + (c.montantPaye ?? c.montant);
    }
    final entries = byMonth.entries.toList()..sort((a, b) => a.key.compareTo(b.key));
    if (entries.isEmpty) return const SizedBox.shrink();

    final dataMaxY = entries.map((e) => e.value).reduce((a, b) => a > b ? a : b);
    final yMax = (dataMaxY * 1.1 + 1).clamp(1.0, double.infinity);
    final yInterval = yMax / 4;
    final spots = entries.asMap().entries.map((e) => FlSpot(e.key.toDouble(), e.value.value)).toList();
    final n = spots.length;
    final xInterval = n <= 5 ? 1.0 : (n - 1) / 4;
    final xIntervalSafe = xInterval < 1 ? 1.0 : xInterval;

    return Container(
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: ColorTokens.surface,
        borderRadius: BorderRadius.circular(16),
        border: Border.all(color: ColorTokens.outline),
        boxShadow: [BoxShadow(color: ColorTokens.shadow.withOpacity(0.06), blurRadius: 8, offset: const Offset(0, 2))],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            'Paiements par période',
            style: AppTypography.bodyTextSmall.copyWith(
              fontWeight: FontWeight.w700,
              color: ColorTokens.onSurfaceVariant,
            ),
          ),
          const SizedBox(height: 16),
          SizedBox(
            height: 180,
            child: LineChart(
              LineChartData(
                gridData: FlGridData(show: true, drawVerticalLine: false),
                titlesData: FlTitlesData(
                  leftTitles: AxisTitles(
                    sideTitles: SideTitles(
                      showTitles: true,
                      reservedSize: 44,
                      interval: yInterval,
                      getTitlesWidget: (v, _) => Text(_formatAxisAmount(v), style: const TextStyle(fontSize: 10)),
                    ),
                  ),
                  bottomTitles: AxisTitles(
                    sideTitles: SideTitles(
                      showTitles: true,
                      reservedSize: 28,
                      interval: xIntervalSafe,
                      getTitlesWidget: (v, _) {
                        final i = v.round();
                        if (i >= 0 && i < entries.length) {
                          final k = entries[i].key;
                          final m = k % 12 == 0 ? 12 : k % 12;
                          final y = k % 12 == 0 ? (k ~/ 12) - 1 : (k ~/ 12);
                          return Text(_formatAxisPeriod(m, y), style: const TextStyle(fontSize: 10));
                        }
                        return const SizedBox.shrink();
                      },
                    ),
                  ),
                  topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
                  rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
                ),
                borderData: FlBorderData(show: true, border: Border(bottom: BorderSide(color: ColorTokens.outline), left: BorderSide(color: ColorTokens.outline))),
                minX: 0,
                maxX: (spots.length - 1).toDouble(),
                minY: 0,
                maxY: yMax,
                lineBarsData: [
                  LineChartBarData(
                    spots: spots,
                    isCurved: true,
                    color: UnionFlowColors.unionGreen,
                    barWidth: 2,
                    isStrokeCapRound: true,
                    dotData: const FlDotData(show: true),
                    belowBarData: BarAreaData(show: true, color: UnionFlowColors.unionGreen.withOpacity(0.15)),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildProchainesEcheances() {
    final list = _cotisations ?? [];
    final aRegler = list.where((c) => c.statut != ContributionStatus.payee && c.statut != ContributionStatus.annulee).toList();
    aRegler.sort((a, b) => a.dateEcheance.compareTo(b.dateEcheance));
    final top = aRegler.take(5).toList();
    if (top.isEmpty) return const SizedBox.shrink();

    return Container(
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: ColorTokens.surface,
        borderRadius: BorderRadius.circular(16),
        border: Border.all(color: ColorTokens.outline),
        boxShadow: [BoxShadow(color: ColorTokens.shadow.withOpacity(0.06), blurRadius: 8, offset: const Offset(0, 2))],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            'Prochaines échéances à régler',
            style: AppTypography.bodyTextSmall.copyWith(
              fontWeight: FontWeight.w700,
              color: ColorTokens.onSurfaceVariant,
            ),
          ),
          const SizedBox(height: 12),
          ...top.map((c) => Padding(
                padding: const EdgeInsets.only(bottom: 10),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      _formatDate(c.dateEcheance.toIso8601String()),
                      style: AppTypography.bodyTextSmall,
                    ),
                    Text(
                      _currencyFormat.format(c.montant),
                      style: AppTypography.bodyTextSmall.copyWith(
                        fontWeight: FontWeight.w600,
                        color: UnionFlowColors.terracotta,
                      ),
                    ),
                  ],
                ),
              )),
        ],
      ),
    );
  }

  double _toDouble(dynamic v) {
    if (v == null) return 0;
    if (v is num) return v.toDouble();
    if (v is String) return double.tryParse(v) ?? 0;
    return 0;
  }

  String _formatDate(String isoOrRaw) {
    try {
      final dt = DateTime.tryParse(isoOrRaw);
      if (dt != null) {
        const months = ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc'];
        return '${dt.day} ${months[dt.month - 1]} ${dt.year}';
      }
    } catch (e, st) {
      AppLogger.warning('MesStatistiquesCotisations: format date invalide', tag: isoOrRaw);
    }
    return isoOrRaw;
  }

  String _formatShortAmount(double v) {
    if (v >= 1000) return '${(v / 1000).toStringAsFixed(0)}k';
    return v.toStringAsFixed(0);
  }

  /// Format court pour l’axe Y : 0, 25 k, 50 k, 1 M — peu de libellés, lisibles.
  String _formatAxisAmount(double v) {
    if (v >= 1000000) return '${(v / 1000000).toStringAsFixed(1)} M';
    if (v >= 1000) return '${(v / 1000).toStringAsFixed(0)} k';
    if (v < 1) return '0';
    return v.toStringAsFixed(0);
  }

  String _monthShort(int m) {
    const t = ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc'];
    return m >= 1 && m <= 12 ? t[m - 1] : '';
  }

  /// Libellé court pour l’axe X : "Jan 25", "Avr 25" — peu de caractères.
  String _formatAxisPeriod(int month, int year) {
    final shortYear = year % 100;
    return '${_monthShort(month)} $shortYear';
  }
}
