import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:path_provider/path_provider.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/controllers/notification/firebase_notification_manger.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:http/http.dart' as http;
import 'package:test_sa/modules/cx_module/chat/model/chat_attachment_model.dart';
import 'api_client.dart';
import 'model/chat_login_response_model.dart';
import 'model/chat_participant_model.dart';
import 'model/get_search_user_chat_model.dart';
import 'model/get_single_user_chat_list_model.dart';
import 'model/get_user_login_token_model.dart' as userLoginTokenModel;
import 'model/user_chat_history_model.dart';

// import 'package:mohem_flutter_app/api/api_client.dart';
// import 'package:mohem_flutter_app/app_state/app_state.dart';
// import 'package:mohem_flutter_app/classes/consts.dart';
// import 'package:mohem_flutter_app/classes/utils.dart';
// import 'package:mohem_flutter_app/exceptions/api_exception.dart';
// import 'package:mohem_flutter_app/main.dart';
// import 'package:mohem_flutter_app/models/chat/chat_user_image_model.dart';
// import 'package:mohem_flutter_app/models/chat/create_group_request.dart' as createGroup;
// import 'package:mohem_flutter_app/models/chat/get_group_chat_history.dart';
// import 'package:mohem_flutter_app/models/chat/get_search_user_chat_model.dart';
// import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart' as groups;
// import 'package:mohem_flutter_app/models/chat/get_user_groups_by_id.dart';
// import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as user;
// import 'package:mohem_flutter_app/models/chat/make_user_favotire_unfavorite_chat_model.dart' as fav;

//Need to refector this remove unused code.
class ChatApiClient {
  static final ChatApiClient _instance = ChatApiClient._internal();

  ChatApiClient._internal();

  factory ChatApiClient() => _instance;

  ChatLoginResponse? chatLoginResponse;

  Future<ChatLoginResponse?> getChatLoginToken(int moduleId, int requestId, String title, String employeeNumber, String assigneeEmployeeNumber) async {
    String platform;
    if (Platform.isIOS) {
      platform = "IOS";
    } else {
      if (await FirebaseNotificationManger.isGoogleServicesAvailable()) {
        platform = "GOOGLE";
      } else {
        platform = "HUAWEI";
      }
    }
    Response response = await ApiClient().postJsonForResponse(URLs.chatSdkToken, {
      "apiKey": URLs.chatApiKey,
      "employeeNumber": employeeNumber,
      "assigneeEmployeeNumber": assigneeEmployeeNumber,
      "userDetails": {"userName": ApiManager.instance.user?.username, "email": ApiManager.instance.user?.email},
      "contextEnabled": true,
      "moduleCode": moduleId.toString(),
      "referenceId": requestId.toString(),
      // "referenceType": "ticket",
      "title": title,
      "deviceToken": FirebaseNotificationManger.token,
      "isHuaweiDevice": platform == "HUAWEI",
      "platform": platform,
      "voIPToken": null
    });

    if (!kReleaseMode) {
      // logger.i("login-res: " + response.body);
    }
    if (response.statusCode == 200) {
      chatLoginResponse = ChatLoginResponse.fromJson(jsonDecode(response.body));
    }
    return chatLoginResponse;
  }

  Future<ChatParticipantModel?> loadParticipants(int moduleId, int referenceId, String? assigneeEmployeeNumber) async {
    Response response = await ApiClient().getJsonForResponse(
        "${URLs.chatHubUrlApi}/chat/context/$moduleId/$referenceId?assigneeEmployeeNumber=$assigneeEmployeeNumber&requestType=chat&transactionType=17",
        token: chatLoginResponse!.token);

    if (!kReleaseMode) {
      // logger.i("login-res: " + response.body);
    }
    if (response.statusCode == 200) {
      return ChatParticipantModel.fromJson(jsonDecode(response.body));
    } else {
      return null;
    }
  }

  Future<bool> resetCountApi(int moduleCode, int referenceNumber, String? employeeNumber) async {
    final Map<String, dynamic> payload = {
      'moduleCode': "$moduleCode",
      'ReferenceNumber': "$referenceNumber",
    };
    final Response response = await ApiClient().postJsonForResponse(
      URLs.resetMessageCount,
      payload,
      token: chatLoginResponse!.token,
    );
    return response.statusCode == 200;
  }


  Future<List<ChatAttachment>> viewAllDocuments(int moduleId, int referenceId) async {
    Response response = await ApiClient().getJsonForResponse("${URLs.chatHubUrlApi}/attachments/conversation?referenceId=$referenceId&moduleCode=$moduleId", token: chatLoginResponse!.token);

    if (response.statusCode == 200) {
      List data = jsonDecode(response.body)["response"];
      return data.map((elemet) => ChatAttachment.fromJson(elemet)).toList();
    } else {
      return [];
    }
  }

  Future<List<SingleUserChatModel>> loadChatHistory(int moduleId, int referenceId, String myId, String otherId) async {
    Response response = await ApiClient().postJsonForResponse(
        "${URLs.chatHubUrlApi}/UserChatHistory/GetUserChatHistory/$myId/$otherId/0", {"moduleCode": moduleId.toString(), "referenceId": referenceId.toString()},
        token: chatLoginResponse!.token);
    try {
      if (response.statusCode == 200) {
        List data = jsonDecode(response.body);
        return data.map((elemet) => SingleUserChatModel.fromJson(elemet)).toList();

        // return UserChatHistoryModel.fromJson(jsonDecode(response.body));
      } else {
        return [];
      }
    } catch (ex) {
      return [];
    }
  }

/*  Future<ChatResponse?> sendTextMessage(String message, int conversationId) async {
    try {
      Response response =
          await ApiClient().postJsonForResponse("${URLs.chatHubUrlApi}/chat/conversations/$conversationId/messages", {"content": message, "messageType": "Text"}, token: chatLoginResponse!.token);

      if (response.statusCode == 200) {
        return ChatResponse.fromJson(jsonDecode(response.body));
      } else {
        return null;
      }
    } catch (ex) {
      print(ex);
      return null;
    }
  }*/

// Future<ChatUserModel> getChatMemberFromSearch(String searchParam, int cUserId, int pageNo) async {
//   ChatUserModel chatUserModel;
//   Response response = await ApiClient().postJsonForResponse("${ApiConsts.chatLoginTokenUrl}getUserWithStatusAndFavAsync", {"employeeNumber": cUserId, "userName": searchParam, "pageNumber": pageNo},
//       token: AppState().chatDetails!.response!.token);
//   if (!kReleaseMode) {
//     logger.i("res: " + response.body);
//   }
//   chatUserModel = chatUserModelFromJson(response.body);
//   return chatUserModel;
// }

// //Get User Recent Chats
// Future<ChatUserModel> getRecentChats() async {
//   try {
//     Response response =
//
//
//     // await ApiManager.instance.get(URLs.getAllRequestsAndCount,h);
//
//
//     await ApiClient().getJsonForResponse(
//       "${ApiConsts.chatRecentUrl}getchathistorybyuserid",
//       token: AppState().chatDetails!.response!.token,
//     );
//     if (!kReleaseMode) {
//       logger.i("res: " + response.body);
//     }
//     return ChatUserModel.fromJson(
//       json.decode(response.body),
//     );
//   } catch (e) {
//     throw e;
//   }
// }

// // Get Favorite Users
// Future<ChatUserModel> getFavUsers() async {
//   Response favRes = await ApiClient().getJsonForResponse(
//     "${ApiConsts.chatFavUser}getFavUserById/${AppState().chatDetails!.response!.id}",
//     token: AppState().chatDetails!.response!.token,
//   );
//   if (!kReleaseMode) {
//     logger.i("res: " + favRes.body);
//   }
//   return ChatUserModel.fromJson(json.decode(favRes.body));
// }

// //Get User Chat History
// Future<Response> getSingleUserChatHistory({required int senderUID, required int receiverUID, required bool loadMore, bool isNewChat = false, required int paginationVal}) async {
//   try {
//     Response response = await ApiClient().getJsonForResponse(
//       "${ApiConsts.chatSingleUserHistoryUrl}GetUserChatHistory/$senderUID/$receiverUID/$paginationVal",
//       token: AppState().chatDetails!.response!.token,
//     );
//     if (!kReleaseMode) {
//       logger.i("res: " + response.body);
//     }
//     return response;
//   } catch (e) {
//     getSingleUserChatHistory(senderUID: senderUID, receiverUID: receiverUID, loadMore: loadMore, paginationVal: paginationVal);
//     throw e;
//   }
// }

// //Favorite Users
//   Future<fav.FavoriteChatUser> favUser({required int userID, required int targetUserID}) async {
//     Response response = await ApiClient().postJsonForResponse("${ApiConsts.chatFavUser}addFavUser", {"targetUserId": targetUserID, "userId": userID}, token: AppState().chatDetails!.response!.token);
//     if (!kReleaseMode) {
//       logger.i("res: " + response.body);
//     }
//     fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body);
//     return favoriteChatUser;
//   }

// //UnFavorite Users
// Future<fav.FavoriteChatUser> unFavUser({required int userID, required int targetUserID}) async {
//   try {
//     Response response = await ApiClient().postJsonForResponse(
//       "${ApiConsts.chatFavUser}deleteFavUser",
//       {"targetUserId": targetUserID, "userId": userID},
//       token: AppState().chatDetails!.response!.token,
//     );
//     if (!kReleaseMode) {
//       logger.i("res: " + response.body);
//     }
//     fav.FavoriteChatUser favoriteChatUser = fav.FavoriteChatUser.fromRawJson(response.body);
//     return favoriteChatUser;
//   } catch (e) {
//     e as APIException;
//     throw e;
//   }
// }

// Upload Chat Media
  Future<Object?> uploadMedia(String userId, File file, String fileSource, {Map? jsonData}) async {
    dynamic request = MultipartRequest('POST', Uri.parse('${URLs.chatHubUrlApi}/attachments/upload'));
    request.fields.addAll({'userId': userId, 'fileSource': fileSource});
    if (jsonData != null) {
      request.fields.addAll(jsonData);
    }

    request.files.add(await MultipartFile.fromPath('file', file.path));
    request.headers.addAll({'Authorization': 'Bearer ${chatLoginResponse!.token}'});
    StreamedResponse response = await request.send();
    String data = await response.stream.bytesToString();
    if (!kReleaseMode) {
      print("uploadMedia: $data");
    }
    return jsonDecode(data);
  }

// // Download File For Chat
// Future<Uint8List> downloadURL({required String fileName, required String fileTypeDescription, required int fileSource,required String url}) async {
//   Response response = await ApiClient().postJsonForResponse(
//     "${ApiConsts.chatMediaImageUploadUrl}download",
//     {"fileType": fileTypeDescription, "fileName": fileName, "fileSource": fileSource},
//     token: AppState().chatDetails!.response!.token,
//   );
//   Uint8List data = Uint8List.fromList(response.bodyBytes);
//   return data;
// }

// Download File For Chat
  Future<Uint8List> downloadURL(String url, {required String fileName, required String fileTypeDescription, required int fileSource}) async {
    Response response = await ApiClient().postJsonForResponse(
      url,
      {"fileType": fileTypeDescription, "fileName": fileName, "fileSource": fileSource},
      token: chatLoginResponse!.token,
    );
    Uint8List data = Uint8List.fromList(response.bodyBytes);
    return data;
  }

  /// Downloads a file from a secure URL that uses a 302 redirect.
  ///
  /// [url]: The initial URL that requires the authorization token.
  /// [token]: The Bearer token for authorization.
  /// [saveFileName]: The name to give the downloaded file (e.g., 'my-document.pdf').
  Future<File?> downloadFileWithHttp(String url, {required String fileName, required String fileTypeDescription, required int fileSource}) async {
    final client = http.Client();
    File? file;
    try {
      final request = http.Request('GET', Uri.parse(url));
      request.headers['Authorization'] = 'Bearer ${chatLoginResponse!.token}';

      // This is the most important part: prevent automatic redirection.
      request.followRedirects = false;
      final streamedResponse = await client.send(request);

      // --- Step 2: Check the response and handle the redirect ---

      // Check for a 302 redirect status.
      if (streamedResponse.statusCode == 302) {
        // Get the new URL from the 'Location' header.
        final redirectUrl = streamedResponse.headers['location'];

        if (redirectUrl == null) {
          throw Exception('302 Redirect did not contain a Location header.');
        }

        final fileResponse = await http.get(Uri.parse(redirectUrl), headers: {'Authorization': 'Bearer ${chatLoginResponse!.token}'});

        if (fileResponse.statusCode == 200) {
          // Get a safe directory to save the file.
          final dir = await getTemporaryDirectory();
          file = File('${dir.path}/$fileName');

          // Write the file to disk.
          await file.writeAsBytes(fileResponse.bodyBytes);
          print("File downloaded successfully and saved to: ${file.path}");
        } else {
          // The download from the final URL failed.
          throw Exception('Failed to download from redirect URL. Status: ${fileResponse.statusCode}');
        }
      }
      // Handle cases where the server might just send the file directly.
      else if (streamedResponse.statusCode == 200) {
        print("Server sent file directly without redirect.");
        final dir = await getTemporaryDirectory();
        file = File('${dir.path}/$fileName');
        await file.writeAsBytes(await streamedResponse.stream.toBytes());
        print("File downloaded successfully and saved to: ${file.path}");
      }
      // Handle other error statuses.
      else {
        throw Exception('Failed to initiate download. Status: ${streamedResponse.statusCode}');
      }
    } catch (e) {
      print("An error occurred during download: $e");
    } finally {
      // Always close the client to free up resources.
      client.close();
    }

    return file;
  }

// //Get Chat Users & Favorite Images
// Future<List<ChatUserImageModel>> getUsersImages({required List<String> encryptedEmails}) async {
//   List<ChatUserImageModel> imagesData = [];
//   Response response = await ApiClient().postJsonForResponse(
//     "${ApiConsts.chatUserImages}images",
//     {"encryptedEmails": encryptedEmails, "fromClient": false},
//     token: AppState().chatDetails!.response!.token,
//   );
//   if (!kReleaseMode) {
//     logger.i("res: " + response.body);
//   }
//   if (response.statusCode == 200) {
//     imagesData = chatUserImageModelFromJson(response.body);
//   } else if (response.statusCode == 500 || response.statusCode == 504) {
//     getUsersImages(encryptedEmails: encryptedEmails);
//   } else {
//     Utils.showToast("Something went wrong while loading images");
//     imagesData = [];
//   }
//   return imagesData;
// }
//
// //group chat apis start here.
// Future<groups.GetUserGroups> getGroupsByUserId() async {
//   try {
//     Response response = await ApiClient().getJsonForResponse(
//       "${ApiConsts.getGroupByUserId}${AppState().chatDetails!.response!.id}",
//       token: AppState().chatDetails!.response!.token,
//     );
//     if (!kReleaseMode) {
//       logger.i("res: " + response.body);
//     }
//     return groups.GetUserGroups.fromRawJson(response.body);
//   } catch (e) {
//     //if fail api returning 500 hence just printing here
//     print(e);
//     throw e;
//   }
// }

// Future<Response> deleteGroup(int? groupId) async {
//   try {
//     Response response = await ApiClient().postJsonForResponse(
//       ApiConsts.deleteGroup,
//       {"groupId": groupId},
//       token: AppState().chatDetails!.response!.token,
//     );
//     if (!kReleaseMode) {
//       logger.i("res: " + response.body);
//     }
//     return response;
//   } catch (e) {
//     //if fail api returning 500 hence just printing here
//     print(e);
//     throw e;
//   }
// }

// Future<Response> updateGroupAdmin(int? groupId, List<GroupUserList> groupList) async {
//   try {
//     Response response = await ApiClient().postJsonForResponse(
//       ApiConsts.updateGroupAdmin,
//       {"groupId": groupId, "groupUserList": groupList},
//       token: AppState().chatDetails!.response!.token,
//     );
//     if (!kReleaseMode) {
//       logger.i("res: " + response.body);
//     }
//     return response;
//   } catch (e) {
//     //if fail api returning 500 hence just printing here
//     print(e);
//     throw e;
//   }
// }

// Future<List<GetGroupChatHistoryAsync>> getGroupChatHistory(int? groupId, List<GroupUserList> groupList) async {
//   try {
//     Response response = await ApiClient().postJsonForResponse(
//       ApiConsts.getGroupChatHistoryAsync,
//       {"groupId": groupId, "targetUserList": groupList, "CurrentId": AppState().chatDetails!.response!.id},
//       token: AppState().chatDetails!.response!.token,
//     );
//     if (!kReleaseMode) {
//       logger.i("res: " + response.body);
//     }
//     List<GetGroupChatHistoryAsync> groupChat = [];
//     List groupChatData = json.decode(response.body);
//     for (var i in groupChatData) {
//       groupChat.add(GetGroupChatHistoryAsync.fromJson(i));
//     }
//
//     groupChat.sort((a, b) => b.createdDate!.compareTo(a.createdDate!));
//     return groupChat;
//     // for(GetGroupChatHistoryAsync i in groupChat) {
//     //   return GetGroupChatHistoryAsync.fromJson(jsonEncode(i));
//     // }
//   } catch (e) {
//     //if fail api returning 500 hence just printing here
//     print(e);
//     throw e;
//   }
// }

// Future addGroupAndUsers(createGroup.CreateGroupRequest request) async {
//   try {
//     Response response = await ApiClient().postJsonForResponse(
//       ApiConsts.addGroupsAndUsers,
//       request,
//       token: AppState().chatDetails!.response!.token,
//     );
//     if (!kReleaseMode) {
//       logger.i("res: " + response.body);
//     }
//     return response.body;
//   } catch (e) {
//     //if fail api returning 500 hence just printing here
//     print(e);
//     throw e;
//   }
// }

// Future updateGroupAndUsers(createGroup.CreateGroupRequest request) async {
//   try {
//     Response response = await ApiClient().postJsonForResponse(
//       ApiConsts.updateGroupsAndUsers,
//       request,
//       token: AppState().chatDetails!.response!.token,
//     );
//     if (!kReleaseMode) {
//       logger.i("res: " + response.body);
//     }
//     return response.body;
//   } catch (e) {
//     //if fail api returning 500 hence just printing here
//     print(e);
//     throw e;
//   }
// }
}
