import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:p_tits_pas/models/user.dart';
import 'package:p_tits_pas/models/parent_model.dart';
import 'package:p_tits_pas/models/assistante_maternelle_model.dart';
import 'package:p_tits_pas/services/api/api_config.dart';
import 'package:p_tits_pas/services/api/tokenService.dart';

class UserService {
  static Future<Map<String, String>> _headers() async {
    final token = await TokenService.getToken();
    return token != null
        ? ApiConfig.authHeaders(token)
        : Map<String, String>.from(ApiConfig.headers);
  }

  static String? _toStr(dynamic v) {
    if (v == null) return null;
    if (v is String) return v;
    return v.toString();
  }

  // Récupérer la liste des gestionnaires (endpoint dédié)
  static Future<List<AppUser>> getGestionnaires() async {
    final response = await http.get(
      Uri.parse('${ApiConfig.baseUrl}${ApiConfig.gestionnaires}'),
      headers: await _headers(),
    );

    if (response.statusCode != 200) {
      final err = jsonDecode(response.body) as Map<String, dynamic>?;
      throw Exception(
          _toStr(err?['message']) ?? 'Erreur chargement gestionnaires');
    }

    final List<dynamic> data = jsonDecode(response.body);
    return data.map((e) => AppUser.fromJson(e)).toList();
  }

  static Future<AppUser> createGestionnaire({
    required String nom,
    required String prenom,
    required String email,
    required String password,
    required String telephone,
    String? relaisId,
  }) async {
    final response = await http.post(
      Uri.parse('${ApiConfig.baseUrl}${ApiConfig.gestionnaires}'),
      headers: await _headers(),
      body: jsonEncode(<String, dynamic>{
        'nom': nom,
        'prenom': prenom,
        'email': email,
        'password': password,
        'telephone': telephone,
        'cguAccepted': true,
        'relaisId': relaisId,
      }),
    );

    if (response.statusCode != 200 && response.statusCode != 201) {
      final decoded = jsonDecode(response.body);
      if (decoded is Map<String, dynamic>) {
        final message = decoded['message'];
        if (message is List && message.isNotEmpty) {
          throw Exception(message.join(' - '));
        }
        throw Exception(_toStr(message) ?? 'Erreur création gestionnaire');
      }
      throw Exception('Erreur création gestionnaire');
    }

    final data = jsonDecode(response.body) as Map<String, dynamic>;
    return AppUser.fromJson(data);
  }

  static Future<AppUser> createAdministrateur({
    required String nom,
    required String prenom,
    required String email,
    required String password,
    required String telephone,
  }) async {
    final response = await http.post(
      Uri.parse('${ApiConfig.baseUrl}${ApiConfig.users}/admin'),
      headers: await _headers(),
      body: jsonEncode(<String, dynamic>{
        'nom': nom,
        'prenom': prenom,
        'email': email,
        'password': password,
        'telephone': telephone,
      }),
    );

    if (response.statusCode != 200 && response.statusCode != 201) {
      final decoded = jsonDecode(response.body);
      if (decoded is Map<String, dynamic>) {
        final message = decoded['message'];
        if (message is List && message.isNotEmpty) {
          throw Exception(message.join(' - '));
        }
        throw Exception(_toStr(message) ?? 'Erreur création administrateur');
      }
      throw Exception('Erreur création administrateur');
    }

    final data = jsonDecode(response.body) as Map<String, dynamic>;
    return AppUser.fromJson(data);
  }

  // Récupérer la liste des parents
  static Future<List<ParentModel>> getParents() async {
    final response = await http.get(
      Uri.parse('${ApiConfig.baseUrl}${ApiConfig.parents}'),
      headers: await _headers(),
    );

    if (response.statusCode != 200) {
      final err = jsonDecode(response.body) as Map<String, dynamic>?;
      throw Exception(_toStr(err?['message']) ?? 'Erreur chargement parents');
    }

    final List<dynamic> data = jsonDecode(response.body);
    return data.map((e) => ParentModel.fromJson(e)).toList();
  }

  // Récupérer la liste des assistantes maternelles
  static Future<List<AssistanteMaternelleModel>>
      getAssistantesMaternelles() async {
    final response = await http.get(
      Uri.parse('${ApiConfig.baseUrl}${ApiConfig.assistantesMaternelles}'),
      headers: await _headers(),
    );

    if (response.statusCode != 200) {
      final err = jsonDecode(response.body) as Map<String, dynamic>?;
      throw Exception(_toStr(err?['message']) ?? 'Erreur chargement AM');
    }

    final List<dynamic> data = jsonDecode(response.body);
    return data.map((e) => AssistanteMaternelleModel.fromJson(e)).toList();
  }

  // Récupérer la liste des administrateurs (via /users filtré ou autre)
  // Pour l'instant on va utiliser /users et filtrer côté client si on est super admin
  static Future<List<AppUser>> getAdministrateurs() async {
    // TODO: Endpoint dédié ou filtrage
    // En attendant, on retourne une liste vide ou on tente /users
    try {
      final response = await http.get(
        Uri.parse('${ApiConfig.baseUrl}${ApiConfig.users}'),
        headers: await _headers(),
      );

      if (response.statusCode == 200) {
        final List<dynamic> data = jsonDecode(response.body);
        return data
            .map((e) => AppUser.fromJson(e))
            .where((u) => u.role == 'administrateur' || u.role == 'super_admin')
            .toList();
      }
    } catch (e) {
      // On garde un fallback vide pour ne pas bloquer l'UI admin.
    }
    return [];
  }

  static Future<AppUser> createAdmin({
    required String nom,
    required String prenom,
    required String email,
    required String password,
    required String telephone,
  }) async {
    final response = await http.post(
      Uri.parse('${ApiConfig.baseUrl}${ApiConfig.users}/admin'),
      headers: await _headers(),
      body: jsonEncode(<String, dynamic>{
        'nom': nom,
        'prenom': prenom,
        'email': email,
        'password': password,
        'telephone': telephone,
      }),
    );

    if (response.statusCode != 200 && response.statusCode != 201) {
      final decoded = jsonDecode(response.body);
      if (decoded is Map<String, dynamic>) {
        final message = decoded['message'];
        if (message is List && message.isNotEmpty) {
          throw Exception(message.join(' - '));
        }
        throw Exception(_toStr(message) ?? 'Erreur création administrateur');
      }
      throw Exception('Erreur création administrateur');
    }

    final data = jsonDecode(response.body) as Map<String, dynamic>;
    return AppUser.fromJson(data);
  }

  static Future<AppUser> updateAdmin({
    required String adminId,
    required String nom,
    required String prenom,
    required String email,
    required String telephone,
    String? password,
  }) async {
    final body = <String, dynamic>{
      'nom': nom,
      'prenom': prenom,
      'email': email,
      'telephone': telephone,
    };

    if (password != null && password.trim().isNotEmpty) {
      body['password'] = password.trim();
    }

    final response = await http.patch(
      Uri.parse('${ApiConfig.baseUrl}${ApiConfig.users}/$adminId'),
      headers: await _headers(),
      body: jsonEncode(body),
    );

    if (response.statusCode != 200) {
      final decoded = jsonDecode(response.body);
      if (decoded is Map<String, dynamic>) {
        final message = decoded['message'];
        if (message is List && message.isNotEmpty) {
          throw Exception(message.join(' - '));
        }
        throw Exception(_toStr(message) ?? 'Erreur modification administrateur');
      }
      throw Exception('Erreur modification administrateur');
    }

    final data = jsonDecode(response.body) as Map<String, dynamic>;
    return AppUser.fromJson(data);
  }

  static Future<void> updateGestionnaireRelais({
    required String gestionnaireId,
    required String? relaisId,
  }) async {
    final response = await http.patch(
      Uri.parse(
          '${ApiConfig.baseUrl}${ApiConfig.gestionnaires}/$gestionnaireId'),
      headers: await _headers(),
      body: jsonEncode(<String, dynamic>{'relaisId': relaisId}),
    );

    if (response.statusCode != 200 && response.statusCode != 204) {
      final err = jsonDecode(response.body) as Map<String, dynamic>?;
      throw Exception(
        _toStr(err?['message']) ?? 'Erreur rattachement relais au gestionnaire',
      );
    }
  }

  static Future<AppUser> updateGestionnaire({
    required String gestionnaireId,
    required String nom,
    required String prenom,
    required String email,
    String? telephone,
    required String? relaisId,
    String? password,
  }) async {
    final body = <String, dynamic>{
      'nom': nom,
      'prenom': prenom,
      'email': email,
      'relaisId': relaisId,
    };

    if (telephone != null && telephone.trim().isNotEmpty) {
      body['telephone'] = telephone.trim();
    }

    if (password != null && password.trim().isNotEmpty) {
      body['password'] = password.trim();
    }

    final response = await http.patch(
      Uri.parse('${ApiConfig.baseUrl}${ApiConfig.gestionnaires}/$gestionnaireId'),
      headers: await _headers(),
      body: jsonEncode(body),
    );

    if (response.statusCode != 200) {
      final decoded = jsonDecode(response.body);
      if (decoded is Map<String, dynamic>) {
        final message = decoded['message'];
        if (message is List && message.isNotEmpty) {
          throw Exception(message.join(' - '));
        }
        throw Exception(_toStr(message) ?? 'Erreur modification gestionnaire');
      }
      throw Exception('Erreur modification gestionnaire');
    }

    final data = jsonDecode(response.body) as Map<String, dynamic>;
    return AppUser.fromJson(data);
  }

  static Future<AppUser> updateAdministrateur({
    required String adminId,
    required String nom,
    required String prenom,
    required String email,
    String? telephone,
    String? password,
  }) async {
    final body = <String, dynamic>{
      'nom': nom,
      'prenom': prenom,
      'email': email,
    };

    if (telephone != null && telephone.trim().isNotEmpty) {
      body['telephone'] = telephone.trim();
    }

    if (password != null && password.trim().isNotEmpty) {
      body['password'] = password.trim();
    }

    final response = await http.patch(
      Uri.parse('${ApiConfig.baseUrl}${ApiConfig.users}/$adminId'),
      headers: await _headers(),
      body: jsonEncode(body),
    );

    if (response.statusCode != 200) {
      final decoded = jsonDecode(response.body);
      if (decoded is Map<String, dynamic>) {
        final message = decoded['message'];
        if (message is List && message.isNotEmpty) {
          throw Exception(message.join(' - '));
        }
        throw Exception(_toStr(message) ?? 'Erreur modification administrateur');
      }
      throw Exception('Erreur modification administrateur');
    }

    final data = jsonDecode(response.body) as Map<String, dynamic>;
    return AppUser.fromJson(data);
  }

  static Future<void> deleteUser(String userId) async {
    final response = await http.delete(
      Uri.parse('${ApiConfig.baseUrl}${ApiConfig.users}/$userId'),
      headers: await _headers(),
    );

    if (response.statusCode != 200 && response.statusCode != 204) {
      final decoded = jsonDecode(response.body);
      if (decoded is Map<String, dynamic>) {
        final message = decoded['message'];
        if (message is List && message.isNotEmpty) {
          throw Exception(message.join(' - '));
        }
        throw Exception(_toStr(message) ?? 'Erreur suppression utilisateur');
      }
      throw Exception('Erreur suppression utilisateur');
    }
  }
}
