import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
import 'package:p_tits_pas/utils/enfant_status_utils.dart';

/// Affiche une date ISO / parseable en `dd/MM/yyyy`, avec repli sur la chaîne ou [ifEmpty].
String formatIsoDateFr(String? s, {String ifEmpty = '–'}) {
  if (s == null || s.trim().isEmpty) return ifEmpty;
  try {
    return DateFormat('dd/MM/yyyy').format(DateTime.parse(s.trim()));
  } catch (_) {
    return s.trim();
  }
}

/// Affiche une date ISO en saisie guidée `jj / mm / aaaa`.
String formatIsoDateFrInput(String? s, {String ifEmpty = ''}) {
  if (s == null || s.trim().isEmpty) return ifEmpty;
  try {
    final dt = DateTime.parse(s.trim());
    return formatFrenchDateDigits(
      DateFormat('ddMMyyyy').format(dt),
    );
  } catch (_) {
    return formatFrenchDateDigits(s.replaceAll(RegExp(r'\D'), ''));
  }
}

/// Formate jusqu’à 8 chiffres en `jj / mm / aaaa`.
String formatFrenchDateDigits(String digits) {
  final d = digits.replaceAll(RegExp(r'\D'), '');
  final limited = d.length > 8 ? d.substring(0, 8) : d;
  final buf = StringBuffer();
  for (var i = 0; i < limited.length; i++) {
    if (i == 2 || i == 4) buf.write(' / ');
    buf.write(limited[i]);
  }
  return buf.toString();
}

/// Convertit `dd/MM/yyyy`, `dd / MM / yyyy`, 8 chiffres ou ISO en `yyyy-MM-dd`.
String? parseFrDateToIso(String text) {
  final t = text.trim();
  if (t.isEmpty) return null;

  final digits = t.replaceAll(RegExp(r'\D'), '');
  if (digits.length == 8) {
    final dd = digits.substring(0, 2);
    final mm = digits.substring(2, 4);
    final yyyy = digits.substring(4, 8);
    try {
      return DateFormat('dd/MM/yyyy')
          .parseStrict('$dd/$mm/$yyyy')
          .toIso8601String()
          .split('T')
          .first;
    } catch (_) {}
  }

  try {
    return DateFormat('dd/MM/yyyy')
        .parseStrict(t)
        .toIso8601String()
        .split('T')
        .first;
  } catch (_) {
    try {
      return DateTime.parse(t).toIso8601String().split('T').first;
    } catch (_) {
      return null;
    }
  }
}

({int years, int months, int days}) computeChildAgeParts(
  DateTime birth,
  DateTime reference,
) {
  final birthDay = DateTime(birth.year, birth.month, birth.day);
  final refDay = DateTime(reference.year, reference.month, reference.day);

  var years = refDay.year - birthDay.year;
  var months = refDay.month - birthDay.month;
  var days = refDay.day - birthDay.day;

  if (days < 0) {
    months--;
    final prevMonth = DateTime(refDay.year, refDay.month, 0);
    days += prevMonth.day;
  }
  if (months < 0) {
    years--;
    months += 12;
  }

  return (years: years, months: months, days: days);
}

String _yearLabel(int years) => years == 1 ? '1 an' : '$years ans';

String _monthLabel(int months) => months == 1 ? '1 mois' : '$months mois';

/// Libellé d'âge pour un enfant (liste admin, fiche parent, etc.).
String formatChildAgeLabel({
  String? birthDate,
  String? dueDate,
  String? status,
}) {
  if (status == 'a_naitre' || normalizeEnfantStatus(status) == 'a_naitre') {
    final due = formatIsoDateFr(dueDate, ifEmpty: '');
    if (due.isNotEmpty) return 'Naissance prévue : $due';
    return 'À naître';
  }

  if (birthDate == null || birthDate.trim().isEmpty) return '';

  try {
    final birth = DateTime.parse(birthDate.trim().split('T').first);
    final now = DateTime.now();
    final parts = computeChildAgeParts(birth, now);

    if (parts.years >= 1) {
      if (parts.months > 0) {
        return 'Âge : ${_yearLabel(parts.years)} ${parts.months} mois';
      }
      return 'Âge : ${_yearLabel(parts.years)}';
    }
    if (parts.months >= 1) {
      return 'Âge : ${_monthLabel(parts.months)}';
    }

    final totalDays = DateTime(now.year, now.month, now.day)
        .difference(DateTime(birth.year, birth.month, birth.day))
        .inDays;
    if (totalDays <= 0) return 'Âge : né récemment';
    return 'Âge : $totalDays jour${totalDays > 1 ? 's' : ''}';
  } catch (_) {
    return 'Né le ${formatIsoDateFr(birthDate)}';
  }
}

/// Saisie date FR : 8 chiffres → `jj / mm / aaaa`.
class FrenchDateInputFormatter extends TextInputFormatter {
  const FrenchDateInputFormatter();

  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue,
    TextEditingValue newValue,
  ) {
    final digits = newValue.text.replaceAll(RegExp(r'\D'), '');
    final limited = digits.length > 8 ? digits.substring(0, 8) : digits;
    final formatted = formatFrenchDateDigits(limited);

    final digitsBeforeCursor = newValue.text
        .substring(0, newValue.selection.start.clamp(0, newValue.text.length))
        .replaceAll(RegExp(r'\D'), '')
        .length
        .clamp(0, limited.length);

    return TextEditingValue(
      text: formatted,
      selection: TextSelection.collapsed(
        offset: _cursorOffset(formatted, digitsBeforeCursor),
      ),
    );
  }

  static int _cursorOffset(String formatted, int digitsBeforeCursor) {
    if (digitsBeforeCursor <= 0) return 0;
    var seen = 0;
    for (var i = 0; i < formatted.length; i++) {
      if (RegExp(r'\d').hasMatch(formatted[i])) {
        seen++;
        if (seen >= digitsBeforeCursor) return i + 1;
      }
    }
    return formatted.length;
  }
}
