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: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/get_search_user_chat_model.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;

class ChatApiClient {
  static final ChatApiClient _instance = ChatApiClient._internal();

  ChatApiClient._internal();

  factory ChatApiClient() => _instance;

  Future<user.UserAutoLoginModel> getUserLoginToken() async {
    user.UserAutoLoginModel userLoginResponse = user.UserAutoLoginModel();
    Response response = await ApiClient().postJsonForResponse(
      "${ApiConsts.chatLoginTokenUrl}externaluserlogin",
      {
        "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
        "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG",
        "isMobile": true,
        "deviceToken": AppState().getDeviceToken,
      },
    );

    if (!kReleaseMode) {
      logger.i("login-res: " + response.body);
    }
    if (response.statusCode == 200) {
      userLoginResponse = user.userAutoLoginModelFromJson(response.body);
    } else if (response.statusCode == 501 || response.statusCode == 502 || response.statusCode == 503 || response.statusCode == 504) {
      getUserLoginToken();
    } else {
      userLoginResponse = user.userAutoLoginModelFromJson(response.body);
      Utils.showToast(userLoginResponse.errorResponses!.first.message!);
    }
    return userLoginResponse;
  }

  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 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) async {
    if (kDebugMode) {
      print("${ApiConsts.chatMediaImageUploadUrl}upload");
      print(AppState().chatDetails!.response!.token);
    }

    dynamic request = MultipartRequest('POST', Uri.parse('${ApiConsts.chatMediaImageUploadUrl}upload'));
    request.fields.addAll({'userId': userId, 'fileSource': '1'});
    request.files.add(await MultipartFile.fromPath('files', file.path));
    request.headers.addAll({'Authorization': 'Bearer ${AppState().chatDetails!.response!.token}'});
    StreamedResponse response = await request.send();
    String data = await response.stream.bytesToString();
    if (!kReleaseMode) {
      logger.i("res: " + data);
    }
    return jsonDecode(data);
  }

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

  //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;
  }
}
