// lib/services/api_service.dart
import 'package:get/get.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;

import 'package:gifunavi/model/entry.dart';
import 'package:gifunavi/model/event.dart';
import 'package:gifunavi/model/team.dart';
import 'package:gifunavi/model/category.dart';
import 'package:gifunavi/model/user.dart';
import 'package:gifunavi/pages/index/index_controller.dart';
import '../routes/app_pages.dart';
import '../utils/const.dart';
import 'package:intl/intl.dart';



class ApiService extends GetxService{
  static ApiService get to => Get.find<ApiService>();
  String serverUrl = '';
  String baseUrl = '';
  String token = 'your-auth-token';

  Future<ApiService> init() async {
    try {
      //if (!Get.isRegistered<IndexController>()) {
      //  Get.put(IndexController(apiService: Get.find<ApiService>()));
      //}

      // ここで必要な初期化処理を行う
      serverUrl = ConstValues.currentServer();
      baseUrl = '$serverUrl/api';
      //await Future.delayed(Duration(seconds: 2)); // 仮の遅延（実際の初期化処理に置き換えてください）
      print('ApiService initialized successfully . baseUrl = $baseUrl');
      return this;
    } catch(e) {
      print('Error in ApiService initialization: $e');
      rethrow; // エラーを再スローして、呼び出し元で処理できるようにする
      //return this;
    }
  }

  /*
  このメソッドは以下のように動作します：

  まず、渡された type パラメータに基づいて、どのクラスのフィールドを扱っているかを判断します。
  次に、クラス内で fieldName に対応する期待される型を返します。
  クラスや フィールド名が予期されていないものである場合、'Unknown' または 'Unknown Type' を返します。

  このメソッドを ApiService クラスに追加することで、_printDataComparison メソッドは各フィールドの期待される型を正確に表示できるようになります。
  さらに、このメソッドを使用することで、API レスポンスのデータ型が期待と異なる場合に簡単に検出できるようになります。例えば、Category クラスの duration フィールドが整数型（秒数）で期待されているのに対し、API が文字列を返した場合、すぐに問題を特定できます。
  注意点として、API のレスポンス形式が変更された場合や、新しいフィールドが追加された場合は、このメソッドも更新する必要があります。そのため、API の変更とクライアントサイドのコードの同期を保つことが重要です。
   */

  Future<String> getToken2 () async
  {
    // IndexControllerの初期化を待つ
    if (!Get.isRegistered<IndexController>()) {
      Get.find<IndexController>();
    }
    final indexController = Get.find<IndexController>();
    if (indexController.currentUser.isNotEmpty) {
      token = indexController.currentUser[0]['token'] ?? '';
      print("Get token = $token");
    }else{
      token = "";
    }
    return token;
  }

  String getToken()
  {
    // IndexControllerの初期化を待つ
    if (!Get.isRegistered<IndexController>()) {
      Get.find<IndexController>();
    }
    final indexController = Get.find<IndexController>();
    if (indexController.currentUser.isNotEmpty) {
      token = indexController.currentUser[0]['token'] ?? '';
      print("Get token = $token");
    }else{
      token = "";
    }
    return token;
  }

  Future<dynamic> _handleRequest(Future<http.Response> Function() request) async {
    try {
      final response = await request();
      if (response.statusCode == 200 || response.statusCode == 201) {
        return json.decode(utf8.decode(response.bodyBytes));
      } else if (response.statusCode == 401) {
        await _handleUnauthorized();
        throw Exception('Authentication failed. Please log in again.');
      } else {
        throw Exception('Request failed with status: ${response.statusCode}');
      }
    } catch (e) {
      print('API request error: $e');
      rethrow;
    }
  }

  Future<void> _handleUnauthorized() async {
    // トークンをクリアし、ユーザーをログアウトさせる
    final indexController = Get.find<IndexController>();
    await indexController.logout();
    Get.offAllNamed(AppPages.LOGIN);
  }

  Future<List<Team>> getTeams() async {
    final token = await getToken2();
    return _handleRequest(() => http.get(
      Uri.parse('$baseUrl/teams/'),
      headers: {'Authorization': 'Token $token', "Content-Type": "application/json; charset=UTF-8"},
    )).then((data) => (data as List).map((json) => Team.fromJson(json)).toList());
  }


  Future<List<Team>> getTeams_old() async {
    init();
    final token = await getToken2();

    try {

      final response = await http.get(
        Uri.parse('$baseUrl/teams/'),
        headers: {'Authorization': 'Token $token',"Content-Type": "application/json; charset=UTF-8"},
      );

      if (response.statusCode == 200) {
        // UTF-8でデコード
        final decodedResponse = utf8.decode(response.bodyBytes);
        //print('User Response body: $decodedResponse');
        List<dynamic> teamsJson = json.decode(decodedResponse);

        List<Team> teams = [];
        for (var teamJson in teamsJson) {
          //print('\nTeam Data:');
          //_printDataComparison(teamJson, Team);
          teams.add(Team.fromJson(teamJson));
        }
        return teams;
      } else {
        throw Exception('Failed to load teams. Status code: ${response.statusCode}');
      }
    } catch (e, stackTrace) {
      print('Error in getTeams: $e');
      print('Stack trace: $stackTrace');
      rethrow;
    }
  }



  Future<List<NewCategory>> getCategories() async {
    init();
    getToken();

    try {
      final response = await http.get(
        Uri.parse('$baseUrl/categories/'),
        headers: {'Authorization': 'Token $token',"Content-Type": "application/json; charset=UTF-8"},
      );

      if (response.statusCode == 200) {
        final decodedResponse = utf8.decode(response.bodyBytes);
        print('User Response body: $decodedResponse');
        List<dynamic> categoriesJson = json.decode(decodedResponse);

        List<NewCategory> categories = [];
        for (var categoryJson in categoriesJson) {
          try {
            //print('\nCategory Data:');
            //_printDataComparison(categoryJson, NewCategory);
            categories.add(NewCategory.fromJson(categoryJson));
          }catch(e){
            print('Error parsing category: $e');
            print('Problematic JSON: $categoryJson');
          }
        }

        return categories;
      } else {
        throw Exception(
            'Failed to load categories. Status code: ${response.statusCode}');
      }
    }catch(e, stackTrace){
      print('Error in getCategories: $e');
      print('Stack trace: $stackTrace');
      rethrow;
    }
  }

  Future<NewCategory> getZekkenNumber(int categoryId) async {
    final token = await getToken2();
    return _handleRequest(() => http.post(
      Uri.parse('$baseUrl/categories-viewset/$categoryId/get_zekken_number/'),
      headers: {'Authorization': 'Token $token', "Content-Type": "application/json; charset=UTF-8"},
    )).then((data) => NewCategory.fromJson(data));
  }

  Future<NewCategory> getZekkenNumber_old(int categoryId) async {
    try {
      final response = await http.post(
          Uri.parse('$baseUrl/categories-viewset/$categoryId/get_zekken_number/'),
          headers: {'Authorization': 'Token $token',"Content-Type": "application/json; charset=UTF-8"},
      );
      if (response.statusCode == 200) {
        final decodedResponse = utf8.decode(response.bodyBytes);
        print('User Response body: $decodedResponse');
        final categoriesJson = json.decode(decodedResponse);

        return NewCategory.fromJson(categoriesJson);
      } else {
        throw Exception('Failed to increment category number');
      }
    } catch (e) {
      throw Exception('Error incrementing category number: $e');
    }
  }

  Future<User> getCurrentUser() async {
    init();
    final token = getToken();

    try {
      final response = await http.get(
        Uri.parse('$baseUrl/user/'),
        headers: {'Authorization': 'Token $token',"Content-Type": "application/json; charset=UTF-8"},
      );

      if (response.statusCode == 200) {
        final decodedResponse = utf8.decode(response.bodyBytes);
        //print('User Response body: $decodedResponse');
        final jsonData = json.decode(decodedResponse);

        //print('\nUser Data Comparison:');
        //_printDataComparison(jsonData, User);

        return User.fromJson(jsonData);
      } else if (response.statusCode == 401) {
        // トークンが無効な場合、ログアウトしてログインページにリダイレクト
        await Get.find<IndexController>().logout();
        //indexController.logout();
        Get.offAllNamed(AppPages.LOGIN);
        throw Exception('Authentication failed. Please log in again.');

      } else {
        throw Exception('Failed to get current user. Status code: ${response.statusCode}');
      }
    } catch (e, stackTrace) {
      print('Error in getCurrentUser: $e');
      print('Stack trace: $stackTrace');
      rethrow;
    }
  }

  void _printDataComparison(Map<String, dynamic> data, Type expectedType) {
    print('Field\t\t| Expected Type\t| Actual Type\t| Actual Value');
    print('------------------------------------------------------------');
    data.forEach((key, value) {
      String expectedFieldType = _getExpectedFieldType(expectedType, key);
      _printComparison(key, expectedFieldType, value);
    });
  }

  String _getExpectedFieldType(Type type, String fieldName) {
    // This method should return the expected type for each field based on the class definition
    // You might need to implement this based on your class structures

    switch (type) {
      case NewCategory:
        switch (fieldName) {
          case 'id': return 'int';
          case 'category_name': return 'String';
          case 'category_number': return 'int';
          case 'duration': return 'int (seconds)';
          case 'num_of_member': return 'int';
          case 'family': return 'bool';
          case 'female': return 'bool';
          default: return 'Unknown';
        }
      case Team:
        switch (fieldName) {
          case 'id': return 'int';
          case 'zekken_number': return 'String';
          case 'team_name': return 'String';
          case 'category': return 'NewCategory (Object)';
          case 'owner': return 'User (Object)';
          default: return 'Unknown';
        }
      case User:
        switch (fieldName) {
          case 'id': return 'int';
          case 'email': return 'String';
          case 'firstname': return 'String';
          case 'lastname': return 'String';
          case 'date_of_birth': return 'String (ISO8601)';
          case 'female': return 'bool';
          case 'is_active': return 'bool';
          default: return 'Unknown';
        }
      default:
        return 'Unknown Type';
    }
  }

  void _printComparison(String fieldName, String expectedType, dynamic actualValue) {
    String actualType = actualValue?.runtimeType.toString() ?? 'null';
    String displayValue = actualValue.toString();
    if (displayValue.length > 50) {
      displayValue = '${displayValue.substring(0, 47)}...';
    }
    print('$fieldName\t\t| $expectedType\t\t| $actualType\t\t| $displayValue');
  }

  Future<Team> createTeam(String teamName, int categoryId) async {
    final token = await getToken2();
    return _handleRequest(() => http.post(
      Uri.parse('$baseUrl/teams/'),
      headers: {'Authorization': 'Token $token', "Content-Type": "application/json; charset=UTF-8"},
      body: json.encode({'team_name': teamName, 'category': categoryId}),
    )).then((data) => Team.fromJson(data));
  }

  Future<Team> createTeam_old(String teamName, int categoryId) async {
    init();
    getToken();

    final response = await http.post(
      Uri.parse('$baseUrl/teams/'),
      headers: {
        'Authorization': 'Token $token',
        "Content-Type": "application/json; charset=UTF-8",
      },
      body: json.encode({
        'team_name': teamName,
        'category': categoryId,
      }),
    );

    if (response.statusCode == 201) {
      final decodedResponse = utf8.decode(response.bodyBytes);
      return Team.fromJson(json.decode(decodedResponse));
    } else {
      throw Exception('Failed to create team');
    }
  }

  Future<Team> updateTeam(int teamId, String teamName, int categoryId) async {
    final token = await getToken2();
    return _handleRequest(() => http.put(
      Uri.parse('$baseUrl/teams/$teamId/'),
      headers: {'Authorization': 'Token $token', "Content-Type": "application/json; charset=UTF-8"},
      body: json.encode({'team_name': teamName, 'category': categoryId}),
    )).then((data) => Team.fromJson(data));
  }

  Future<Team> updateTeam_old(int teamId, String teamName, int categoryId) async {
    init();
    getToken();

    final response = await http.put(
      Uri.parse('$baseUrl/teams/$teamId/'),
      headers: {
        'Authorization': 'Token $token',
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: json.encode({
        'team_name': teamName,
        'category': categoryId,
      }),
    );

    if (response.statusCode == 200) {
      final decodedResponse = utf8.decode(response.bodyBytes);

      return Team.fromJson(json.decode(decodedResponse));
    } else {
      throw Exception('Failed to update team');
    }
  }

  Future<void> deleteTeam(int teamId) async {
    final token = await getToken2();
    await _handleRequest(() => http.delete(
      Uri.parse('$baseUrl/teams/$teamId/'),
      headers: {'Authorization': 'Token $token', "Content-Type": "application/json; charset=UTF-8"},
    ));
  }

  Future<void> deleteTeamold_(int teamId) async {
    init();
    getToken();

    final response = await http.delete(
      Uri.parse('$baseUrl/teams/$teamId/'),
      headers: {'Authorization': 'Token $token','Content-Type': 'application/json; charset=UTF-8'},
    );

    if( response.statusCode == 400) {
      final decodedResponse = utf8.decode(response.bodyBytes);
      print('User Response body: $decodedResponse');
      throw Exception('まだメンバーが残っているので、チームを削除できません。');
    }else if (response.statusCode != 204) {
      throw Exception('Failed to delete team');
    }
  }

  Future<List<User>> getTeamMembers(int teamId) async {
    final token = await getToken2();
    return _handleRequest(() => http.get(
      Uri.parse('$baseUrl/teams/$teamId/members/'),
      headers: {'Authorization': 'Token $token', "Content-Type": "application/json; charset=UTF-8"},
    )).then((data) => (data as List).map((json) => User.fromJson(json)).toList());
  }

  Future<List<User>> getTeamMembers_old(int teamId) async {
    init();
    getToken();

    final response = await http.get(
      Uri.parse('$baseUrl/teams/$teamId/members/'),
      headers: {'Authorization': 'Token $token','Content-Type': 'application/json; charset=UTF-8'},
    );

    if (response.statusCode == 200) {
      final decodedResponse = utf8.decode(response.bodyBytes);
      print('User Response body: $decodedResponse');
      List<dynamic> membersJson = json.decode(decodedResponse);

      return membersJson.map((json) => User.fromJson(json)).toList();
    } else {
      throw Exception('Failed to load team members');
    }
  }

  Future<User> createTeamMember(int teamId, String? email, String? firstname, String? lastname, DateTime? dateOfBirth, bool? female) async {
    final token = await getToken2();
    String? formattedDateOfBirth = dateOfBirth != null ? DateFormat('yyyy-MM-dd').format(dateOfBirth) : null;
    return _handleRequest(() => http.post(
      Uri.parse('$baseUrl/teams/$teamId/members/'),
      headers: {'Authorization': 'Token $token', "Content-Type": "application/json; charset=UTF-8"},
      body: json.encode({
        'email': email,
        'firstname': firstname,
        'lastname': lastname,
        'date_of_birth': formattedDateOfBirth,
        'female': female,
      }),
    )).then((data) => User.fromJson(data));
  }

  Future<User> createTeamMember_old(int teamId, String? email, String? firstname, String? lastname, DateTime? dateOfBirth,bool? female) async {
    init();
    getToken();

    // emailが値を持っている場合の処理
    if (email != null && email.isNotEmpty) {
      firstname ??= "dummy";
      lastname ??= "dummy";
      dateOfBirth ??= DateTime.now();
      female ??= false;
    }

    String? formattedDateOfBirth;
    if (dateOfBirth != null) {
      formattedDateOfBirth = DateFormat('yyyy-MM-dd').format(dateOfBirth);
    }

    final response = await http.post(
      Uri.parse('$baseUrl/teams/$teamId/members/'),
      headers: {
        'Authorization': 'Token $token',
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: json.encode({
        'email': email,
        'firstname': firstname,
        'lastname': lastname,
        'date_of_birth': formattedDateOfBirth,
        'female': female,
      }),
    );

    if (response.statusCode == 200 || response.statusCode == 201) {
      final decodedResponse = utf8.decode(response.bodyBytes);
      return User.fromJson(json.decode(decodedResponse));
    } else {
      throw Exception('Failed to create team member');
    }
  }

  Future<User> updateTeamMember(int teamId, int? memberId, String firstname, String lastname, DateTime? dateOfBirth, bool? female) async {
    final token = await getToken2();
    String? formattedDateOfBirth = dateOfBirth != null ? DateFormat('yyyy-MM-dd').format(dateOfBirth) : null;
    return _handleRequest(() => http.put(
      Uri.parse('$baseUrl/teams/$teamId/members/$memberId/'),
      headers: {'Authorization': 'Token $token', "Content-Type": "application/json; charset=UTF-8"},
      body: json.encode({
        'firstname': firstname,
        'lastname': lastname,
        'date_of_birth': formattedDateOfBirth,
        'female': female,
      }),
    )).then((data) => User.fromJson(data));
  }

  Future<User> updateTeamMember_old(int teamId,int? memberId, String firstname, String lastname, DateTime? dateOfBirth,bool? female) async {
    init();
    getToken();

    String? formattedDateOfBirth;
    if (dateOfBirth != null) {
      formattedDateOfBirth = DateFormat('yyyy-MM-dd').format(dateOfBirth);
    }

    final response = await http.put(
      Uri.parse('$baseUrl/teams/$teamId/members/$memberId/'),
      headers: {
        'Authorization': 'Token $token',
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: json.encode({
        'firstname': firstname,
        'lastname': lastname,
        'date_of_birth': formattedDateOfBirth,
        'female': female,
      }),
    );

    if (response.statusCode == 200) {
      final decodedResponse = utf8.decode(response.bodyBytes);
      return User.fromJson(json.decode(decodedResponse));
    } else {
      throw Exception('Failed to update team member');
    }
  }

  Future<void> deleteTeamMember(int teamId, int memberId) async {
    final token = await getToken2();
    await _handleRequest(() => http.delete(
      Uri.parse('$baseUrl/teams/$teamId/members/$memberId/'),
      headers: {'Authorization': 'Token $token', "Content-Type": "application/json; charset=UTF-8"},
    ));
  }

  Future<void> deleteTeamMember_old(int teamId,int memberId) async {
    init();
    getToken();

    final response = await http.delete(
      Uri.parse('$baseUrl/teams/$teamId/members/$memberId/'),
      headers: {'Authorization': 'Token $token'},
    );

    if (response.statusCode != 204) {
      throw Exception('Failed to delete team member');
    }
  }

  Future<void> deleteAllTeamMembers(int teamId) async {
    final response = await http.delete(
      Uri.parse('$baseUrl/teams/$teamId/members/destroy_all/?confirm=true'),
      headers: {'Authorization': 'Token $token'},
    );

    if (response.statusCode != 200) {
      throw Exception('Failed to delete team members');
    }
  }

  Future<void> resendMemberInvitation(int memberId) async {
    init();
    getToken();

    final response = await http.post(
      Uri.parse('$baseUrl/members/$memberId/resend-invitation/'),
      headers: {'Authorization': 'Token $token',        'Content-Type': 'application/json; charset=UTF-8',
      },
    );

    if (response.statusCode != 200) {
      throw Exception('Failed to resend invitation');
    }
  }

  Future<List<Entry>> getEntries() async {
    final token = await getToken2();
    return _handleRequest(() => http.get(
      Uri.parse('$baseUrl/entry/'),
      headers: {'Authorization': 'Token $token', "Content-Type": "application/json; charset=UTF-8"},
    )).then((data) => (data as List).map((json) => Entry.fromJson(json)).toList());
  }

  Future<List<Entry>> getEntries_old() async {
    init();
    getToken();

    final response = await http.get(
      Uri.parse('$baseUrl/entry/'),
      headers: {'Authorization': 'Token $token',        'Content-Type': 'application/json; charset=UTF-8',
      },
    );

    if (response.statusCode == 200) {
      final decodedResponse = utf8.decode(response.bodyBytes);
      List<dynamic> entriesJson = json.decode(decodedResponse);
      return entriesJson.map((json) => Entry.fromJson(json)).toList();
    } else {
      throw Exception('Failed to load entries');
    }
  }

  Future<List<Entry>> getTeamEntries(int teamId) async {
    try {
      final response = await http.get(
        Uri.parse('$baseUrl/teams/$teamId/entries'),
        headers: {'Authorization': 'Token $token'},
      );

      if (response.statusCode == 200) {
        List<dynamic> entriesJson = jsonDecode(response.body);
        return entriesJson.map((json) => Entry.fromJson(json)).toList();
      } else {
        throw Exception('Failed to load team entries: ${response.statusCode}');
      }
    } catch (e) {
      print('Error in getTeamEntries: $e');
      rethrow;
    }
  }

  Future<List<Event>> getEvents() async {
    init();
    getToken();

    final response = await http.get(
      Uri.parse('$baseUrl/new-events/',),
      headers: {'Authorization': 'Token $token',        'Content-Type': 'application/json; charset=UTF-8',
      },
    );

    if (response.statusCode == 200) {
      final decodedResponse = utf8.decode(response.bodyBytes);
      print('Response body: $decodedResponse');
      List<dynamic> eventsJson = json.decode(decodedResponse);

      return eventsJson.map((json) => Event.fromJson(json)).toList();
    } else {
      throw Exception('Failed to load events');
    }
  }

  Future<Entry> createEntry(int teamId, int eventId, int categoryId, DateTime date, String zekkenNumber) async {
    final token = await getToken2();
    String formattedDate = DateFormat('yyyy-MM-dd').format(date);
    return _handleRequest(() => http.post(
      Uri.parse('$baseUrl/entry/'),
      headers: {'Authorization': 'Token $token', "Content-Type": "application/json; charset=UTF-8"},
      body: json.encode({
        'team': teamId,
        'event': eventId,
        'category': categoryId,
        'date': formattedDate,
        'zekken_number': zekkenNumber,
      }),
    )).then((data) => Entry.fromJson(data));
  }

  Future<Entry> createEntry_old(int teamId, int eventId, int categoryId, DateTime date,String zekkenNumber) async {
    init();
    getToken();

    String? formattedDate;
    formattedDate = DateFormat('yyyy-MM-dd').format(date);
  
    final response = await http.post(
      Uri.parse('$baseUrl/entry/'),
      headers: {
        'Authorization': 'Token $token',
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: json.encode({
        'team': teamId,
        'event': eventId,
        'category': categoryId,
        'date': formattedDate,
        'zekken_number':zekkenNumber,
      }),
    );

    if (response.statusCode == 201) {
      final decodedResponse = utf8.decode(response.bodyBytes);

      return Entry.fromJson(json.decode(decodedResponse));
    } else {
      final decodedResponse = utf8.decode(response.bodyBytes);
      print("decodedResponse = $decodedResponse");
      final errorInfo = json.decode(decodedResponse);
      throw Exception(errorInfo['error']);
    }
  }

  Future<void> updateUserInfo(int userId, Entry entry) async {
    final token = await getToken2();
    String formattedDate = DateFormat('yyyy-MM-dd').format(entry.date!);
    await _handleRequest(() => http.put(
      Uri.parse('$baseUrl/userinfo/$userId/'),
      headers: {'Authorization': 'Token $token', "Content-Type": "application/json; charset=UTF-8"},
      body: json.encode({
        'zekken_number': entry.zekkenNumber,
        'event_code': entry.event.eventName,
        'group': entry.team.category.categoryName,
        'team_name': entry.team.teamName,
        'date': formattedDate,
      }),
    ));
  }

  Future<void> updateUserInfo_old(int userId, Entry entry) async {
    init();
    getToken();

    final entryId = entry.id;

    DateTime? date = entry.date;
    String? formattedDate;
    formattedDate = DateFormat('yyyy-MM-dd').format(date!);
  
    final response = await http.put(
      Uri.parse('$baseUrl/userinfo/$userId/'),
      headers: {
        'Authorization': 'Token $token',
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: json.encode({
        'zekken_number': entry.zekkenNumber,
        'event_code': entry.event.eventName,
        'group': entry.team.category.categoryName,
        'team_name': entry.team.teamName,
        'date': formattedDate,
      }),
    );
    if (response.statusCode == 200) {
      final decodedResponse = utf8.decode(response.bodyBytes);
      final updatedUserInfo = json.decode(decodedResponse);
      //Get.find<IndexController>().updateUserInfo(updatedUserInfo);

    } else {
      throw Exception('Failed to update entry');
    }
  }


  Future<Entry> updateEntry(int entryId, int teamId, int eventId, int categoryId, DateTime date,int zekkenNumber) async {
    init();
    getToken();

    String? formattedDate;
    formattedDate = DateFormat('yyyy-MM-dd').format(date);
  
    final response = await http.put(
      Uri.parse('$baseUrl/entry/$entryId/'),
      headers: {
        'Authorization': 'Token $token',
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: json.encode({
        'team': teamId,
        'event': eventId,
        'category': categoryId,
        'date': formattedDate,
        'zekken_number': zekkenNumber,
      }),
    );

    if (response.statusCode == 200) {
      final decodedResponse = utf8.decode(response.bodyBytes);

      return Entry.fromJson(json.decode(decodedResponse));
    } else {
      final decodedResponse = utf8.decode(response.bodyBytes);
      final blk = json.decode(decodedResponse);

      Map<String, dynamic> error_dict = blk[0]['error'];
      String ? error_message = error_dict['non_field_errors'][0].string;

      throw Exception(error_message);
    }
  }

  Future<void> deleteEntry(int entryId) async {
    init();
    getToken();

    final response = await http.delete(
      Uri.parse('$baseUrl/entry/$entryId/'),
      headers: {'Authorization': 'Token $token'},
    );

    if (response.statusCode != 204) {
      throw Exception('Failed to delete entry');
    }
  }

  static Future<bool> updateUserDetail(User user, String token) async {
    String serverUrl = ConstValues.currentServer();
    int? userid = user.id;
    String url = '$serverUrl/api/userdetail/$userid/';

    try {
      String? formattedDate;
      if (user.dateOfBirth != null) {
        formattedDate = DateFormat('yyyy-MM-dd').format(user.dateOfBirth!);
      }
      final http.Response response = await http.put(
        Uri.parse(url),
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
          'Authorization': 'Token $token'
        },
        body: jsonEncode({
          'firstname': user.firstname,
          'lastname': user.lastname,
          'date_of_birth': formattedDate,
          'female': user.female,
        }),
      );

      if (response.statusCode == 200) {
        return true;
      } else {
        print('Update failed with status code: ${response.statusCode}');
        return false;
      }
    } catch (e) {
      print('Error in updateUserDetail: $e');
      return false;
    }
  }

  Future<bool> resetPassword(String email) async {
    init();

    try {
      final response = await http.post(
        Uri.parse('$baseUrl/password-reset/'),
        headers: {
          'Content-Type': 'application/json; charset=UTF-8',
        },
        body: json.encode({
          'email': email,
        }),
      );

      if (response.statusCode == 200) {
        return true;
      } else {
        print('Password reset failed with status code: ${response.statusCode}');
        return false;
      }
    } catch (e) {
      print('Error in resetPassword: $e');
      return false;
    }
  }

  Future<DateTime?> getLastGoalTime(int userId) async {
    try {
      final response = await http.get(
        Uri.parse('$baseUrl/users/$userId/last-goal/'),
        headers: {
          'Authorization': 'Token $token',
          'Content-Type': 'application/json; charset=UTF-8',
        },
      );

      if (response.statusCode == 200) {
        final decodedResponse = json.decode(utf8.decode(response.bodyBytes));
        if (decodedResponse['last_goal_time'] != null) {
          return DateTime.parse(decodedResponse['last_goal_time']).toLocal();
        }
      } else {
        print('Failed to get last goal time. Status code: ${response.statusCode}');
      }
    } catch (e) {
      print('Error in getLastGoalTime: $e');
    }
    return null;
  }

}