import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart';
import 'package:logging/logging.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/models/chat/get_search_user_chat_model.dart';
import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_Model.dart';
import 'package:mohem_flutter_app/models/chat/get_user_login_token_model.dart' as login;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:signalr_netcore/signalr_client.dart';
import 'package:logger/logger.dart' as L;

class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
  List<SingleUserChatModel> userChatHistory = [];
  List<ChatUser>? pChatHistory, searchedChats;
  late HubConnection hubConnection;
  L.Logger logger = L.Logger();
  TextEditingController message = TextEditingController();
  ScrollController scrollController = ScrollController();
  bool isLoading = true;

  Future<void> getUserAutoLoginToken() async {
    String userName = AppState().memberInformationList!.eMPLOYEEEMAILADDRESS!.split("@").first.toString();
    Response response =
        await ApiClient().postJsonForResponse("${ApiConsts.chatServerBaseApiUrl}user/desktopuserlogin", {"userName": userName, "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", "loginType": 2});
    login.UserAutoLoginModel userLoginResponse = login.userAutoLoginModelFromJson(response.body);
    AppState().setchatUserDetails = userLoginResponse;
    await buildHubConnection();
  }

  Future<List<ChatUser>?> getChatMemberFromSearch(String sName, int cUserId) async {
    Response response = await ApiClient().getJsonForResponse(
      "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSearchMember}$sName/$cUserId",
      token: AppState().chatDetails!.response!.token,
    );
    return searchUserJsonModel(response.body);
    logger.d(response.body);
    isLoading = false;
    notifyListeners();
  }

  List<ChatUser> searchUserJsonModel(String str) => List<ChatUser>.from(json.decode(str).map((x) => ChatUser.fromJson(x)));

  void getUserRecentChats() async {
    Response response = await ApiClient().getJsonForResponse(
      "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatRecentUrl}",
      token: AppState().chatDetails!.response!.token,
    );
    ChatUserModel recentChat = userToList(response.body);
    pChatHistory = recentChat.response;
    searchedChats = pChatHistory;
    isLoading = false;
    notifyListeners();
  }

  void getSingleUserChatHistory({required String senderUID, required int receiverUID, required String pagination}) async {
    isLoading = true;
    Response response = await ApiClient().getJsonForResponse(
      "${ApiConsts.chatServerBaseApiUrl}${ApiConsts.chatSingleUserHistoryUrl}/$senderUID/$receiverUID/$pagination",
      token: AppState().chatDetails!.response!.token,
    );
    logger.d(response.statusCode);
    print(response.body);
    if (response.statusCode == 204) {
      userChatHistory = [];
    } else {
      userChatHistory = getSingleUserChatModel(response.body);
    }
    isLoading = false;
    notifyListeners();
  }

  List<SingleUserChatModel> getSingleUserChatModel(String str) => List<SingleUserChatModel>.from(json.decode(str).map((x) => SingleUserChatModel.fromJson(x)));

  ChatUserModel userToList(String str) => ChatUserModel.fromJson(json.decode(str));

  Future<void> buildHubConnection() async {
    HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true);
    hubConnection = await HubConnectionBuilder()
        .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp)
        .withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000])
        .configureLogging(
          Logger("Logs Enabled"),
        )
        .build();
    hubConnection.onclose(
      ({Exception? error}) {
        logger.d(error);
      },
    );
    hubConnection.onreconnecting(
      ({Exception? error}) {
        logger.d(error);
        logger.d("Reconnecting");
      },
    );
    hubConnection.onreconnected(
      ({String? connectionId}) {
        logger.d("Reconnected");
      },
    );
    if (hubConnection.state != HubConnectionState.Connected) {
      await hubConnection.start();
      hubConnection.on("OnUpdateUserStatusAsync", changeStatus);
      hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived);

      // hubConnection.on("OnUserTypingAsync", onUserTyping);
      // hubConnection.on("OnUserCountAsync", userCountAsync);
      // hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
      // hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
    } else {
      hubConnection.on("OnUpdateUserStatusAsync", changeStatus);
      hubConnection.on("OnDeliveredChatUserAsync", onMsgReceived);

      // hubConnection.on("OnUserTypingAsync", onUserTyping);
      // hubConnection.on("OnUserCountAsync", userCountAsync);
      // hubConnection.on("OnUpdateUserChatHistoryWindowsAsync", updateChatHistoryWindow);
      // hubConnection.on("OnGetUserChatHistoryNotDeliveredAsync", chatNotDelivered);
    }
    isLoading = false;
    notifyListeners();
  }

  void userCountAsync(List<Object?>? args) {
    List items = args!.toList();
    print("---------------------------------User Count Async -------------------------------------");
    logger.d(items);
    // for (var user in searchedChats!) {
    //   if (user.id == items.first["id"]) {
    //     user.userStatus = items.first["userStatus"];
    //   }
    // }
    // notifyListeners();
  }

  void updateChatHistoryWindow(List<Object?>? args) {
    List items = args!.toList();
    print("---------------------------------Update Chat History Windows  Async -------------------------------------");
    logger.d(items);
    // for (var user in searchedChats!) {
    //   if (user.id == items.first["id"]) {
    //     user.userStatus = items.first["userStatus"];
    //   }
    // }
    // notifyListeners();
  }

  void chatNotDelivered(List<Object?>? args) {
    List items = args!.toList();
    print("--------------------------------- Chat Not Delivered Windows Async -------------------------------------");
    logger.d(items);
    // for (var user in searchedChats!) {
    //   if (user.id == items.first["id"]) {
    //     user.userStatus = items.first["userStatus"];
    //   }
    // }
    // notifyListeners();
  }

  void changeStatus(List<Object?>? args) {
    //  print("================= Status Online // Offline  ====================");
    List items = args!.toList();
    logger.d(items);
    for (ChatUser user in searchedChats!) {
      if (user.id == items.first["id"]) {
        user.userStatus = items.first["userStatus"];
      }
    }
    notifyListeners();
  }

  void filter(String value) async {
    List<ChatUser>? tmp = [];
    if (value.isEmpty || value == "") {
      tmp = pChatHistory;
    } else {
      for (ChatUser element in pChatHistory!) {
        if (element.userName!.toLowerCase().contains(value.toLowerCase())) {
          tmp.add(element);
        }
      }
    }
    searchedChats = tmp;
    notifyListeners();
  }

  Future<void> onMsgReceived(List<Object?>? parameters) async {
    List<SingleUserChatModel> data = [];
    for (dynamic msg in parameters!) {
      data = getSingleUserChatModel(jsonEncode(msg));
      logger.d(msg);
    }
    userChatHistory.add(data.first);
    notifyListeners();
    scrollDown();
  }

  void onUserTyping(List<Object?>? parameters) {
    print("==================== Typing Active ==================");
    logger.d(parameters);
    for (ChatUser user in searchedChats!) {
      if (user.id == parameters![1] && parameters[0] == true) {
        user.isTyping = parameters[0] as bool?;
      } else {
        Future.delayed(
          const Duration(milliseconds: 500),
          () {
            user.isTyping = false;
          },
        );
      }
    }
    notifyListeners();
  }

  void sendChatMessage(String chatMessage, int targetUserId, String targetUserName) async {
    if (chatMessage == null || chatMessage.isEmpty) {
      return;
    }
    String chatData =
        '{"contant":"$chatMessage","contantNo":"8a129295-36d7-7185-5d34-cc4eec7bcba4","chatEventId":1,"fileTypeId":null,"currentUserId":${AppState().chatDetails!.response!.id},"chatSource":1,"userChatHistoryLineRequestList":[{"isSeen":false,"isDelivered":false,"targetUserId":$targetUserId,"targetUserStatus":1}],"conversationId":"715f8b13-96ee-cd36-cb07-5a982a219982"}';
    await hubConnection.invoke("AddChatUserAsync", args: <Object>[json.decode(chatData)]);
    userChatHistory.add(
      SingleUserChatModel(
        chatEventId: 1,
        chatSource: 1,
        contant: chatMessage,
        contantNo: "8a129295-36d7-7185-5d34-cc4eec7bcba4",
        conversationId: "715f8b13-96ee-cd36-cb07-5a982a219982",
        createdDate: DateTime.now(),
        currentUserId: AppState().chatDetails!.response!.id,
        currentUserName: AppState().chatDetails!.response!.userName,
        targetUserId: targetUserId,
        targetUserName: targetUserName,
      ),
    );
    message.clear();
    notifyListeners();
    scrollDown();
  }

  void scrollDown() {
    scrollController.animateTo(
      scrollController.position.maxScrollExtent + 100,
      curve: Curves.easeOut,
      duration: const Duration(milliseconds: 300),
    );
    notifyListeners();
  }

// void  _scrollListener() {
//    if (scrollController.position.extentAfter.toInt() <= 0 && canCallApi) {
//      if (userChatHistory.length < _ayatTangheemTypeMapped.totalItemsCount) {
//        currentPageNo++;
//        if (widget.tangheemQuery == null) {
//          getTangheemData();
//        } else {
//          getTangheemDataByKeyword();
//        }
//      }
//      canCallApi = false;
//    }
//  }

}
