import 'dart:convert'; import 'dart:io'; import 'package:flutter/foundation.dart'; import '../models/am_registration_data.dart'; import '../models/user_registration_data.dart'; import 'nir_utils.dart'; import 'parent_registration_payload.dart'; /// Body PATCH /auth/reprise-resoumettre. Ticket #112. class ReprisePayload { ReprisePayload._(); static Map parentPatch( UserRegistrationData data, String token, ) { final base = ParentRegistrationPayload.toJson(data); base.remove('email'); base.remove('acceptation_cgu'); base.remove('acceptation_privacy'); base['token'] = token.trim(); final enfants = data.children.asMap().entries.map((e) { final childMap = ParentRegistrationPayload.childToRepriseJson( e.value, e.key, data.parent1.lastName.trim(), ); return childMap; }).toList(); base['enfants'] = enfants; return base; } static Future> amPatch( AmRegistrationData data, String token, { String? existingPhotoUrl, }) async { final body = {'token': token.trim()}; _put(body, 'prenom', data.firstName.trim()); _put(body, 'nom', data.lastName.trim()); _put(body, 'telephone', data.phone.trim()); _put(body, 'adresse', data.streetAddress.trim()); _put(body, 'code_postal', data.postalCode.trim()); _put(body, 'ville', data.city.trim()); body['consentement_photo'] = data.photoConsent; if (data.dateOfBirth != null) { final d = data.dateOfBirth!; body['date_naissance'] = '${d.year}-${d.month.toString().padLeft(2, '0')}-${d.day.toString().padLeft(2, '0')}'; } _put(body, 'lieu_naissance_ville', data.birthCity.trim()); _put(body, 'lieu_naissance_pays', data.birthCountry.trim()); _put(body, 'numero_agrement', data.agrementNumber.trim()); if (data.nir.trim().isNotEmpty) { body['nir'] = normalizeNir(data.nir); } if (data.agreementDate != null) { final d = data.agreementDate!; body['date_agrement'] = '${d.year}-${d.month.toString().padLeft(2, '0')}-${d.day.toString().padLeft(2, '0')}'; } if (data.capacity != null) { body['capacite_accueil'] = data.capacity; } if (data.placesAvailable != null) { body['places_disponibles'] = data.placesAvailable; } if (data.presentationText.trim().isNotEmpty) { body['biographie'] = data.presentationText.trim(); } final photo = await _amPhotoPayload(data, existingPhotoUrl); if (photo != null) { body.addAll(photo); } return body; } static Future?> _amPhotoPayload( AmRegistrationData data, String? existingPhotoUrl, ) async { if (data.photoBytes != null && data.photoBytes!.isNotEmpty) { final mime = _imageMimeForBytes(data.photoBytes!); final fn = (data.photoFilename ?? '').trim(); return { 'photo_base64': 'data:$mime;base64,${base64Encode(data.photoBytes!)}', 'photo_filename': fn.isNotEmpty ? fn : 'photo_am.jpg', }; } if (!kIsWeb && data.photoPath != null && data.photoPath!.isNotEmpty && !data.photoPath!.startsWith('assets/') && !data.photoPath!.startsWith('http')) { try { final file = File(data.photoPath!); if (await file.exists()) { final bytes = await file.readAsBytes(); final mime = _imageMimeForBytes(bytes); return { 'photo_base64': 'data:$mime;base64,${base64Encode(bytes)}', 'photo_filename': _basenameFromPath(data.photoPath!) ?? 'photo_am.jpg', }; } } catch (_) {} } final url = (existingPhotoUrl ?? data.repriseExistingPhotoUrl ?? '').trim(); if (url.isNotEmpty) { return {'photo_url': url}; } return null; } static String _imageMimeForBytes(Uint8List bytes) { if (bytes.length >= 2 && bytes[0] == 0xFF && bytes[1] == 0xD8) { return 'image/jpeg'; } if (bytes.length >= 8 && bytes[0] == 0x89 && bytes[1] == 0x50 && bytes[2] == 0x4E && bytes[3] == 0x47) { return 'image/png'; } return 'image/jpeg'; } static String? _basenameFromPath(String path) { final parts = path.replaceAll('\\', '/').split('/'); return parts.isEmpty ? null : parts.last; } static void _put(Map m, String key, String value) { if (value.isNotEmpty) m[key] = value; } }