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<String, dynamic> 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<Map<String, dynamic>> amPatch(
    AmRegistrationData data,
    String token, {
    String? existingPhotoUrl,
  }) async {
    final body = <String, dynamic>{'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<Map<String, String>?> _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<String, dynamic> m, String key, String value) {
    if (value.isNotEmpty) m[key] = value;
  }
}
