import 'dart:developer';
import 'dart:io';
import 'package:http/io_client.dart';
import 'package:mc_common_app/api/api_client.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependency_injection.dart';
import 'package:mc_common_app/main.dart';
import 'package:mc_common_app/models/chat_models/chat_message_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:signalr_core/signalr_core.dart';

abstract class ChatRepo {
  Future<HubConnection> getHubConnection();

  Future<bool> markMessageAsRead({required List<int> messageIds, required ChatTypeEnum chatTypeEnum});

  Future<List<ChatMessageModel>> getUsersChatMessagesForRequests({
    required int providerId,
    required int customerId,
    required int requestOfferId,
    required int requestId,
    int pageIndex = 0,
    int pageSize = 0,
  });

  Future<List<ChatMessageModel>> getUsersChatMessagesForAds({
    String? userID,
    int? adID,
    int? adsChatBuyerId,
    required bool isForBuyer,
    int pageIndex = 0,
    int pageSize = 0,
  });

  Future<List<ChatMessageModel>> getUsersChatMessagesForGeneralChat({
    String? userID,
    int? adID,
    int? adsChatBuyerId,
    required bool isForBuyer,
    int pageIndex = 0,
    int pageSize = 0,
  });
}

class ChatRepoImp implements ChatRepo {
  ApiClient apiClient = injector.get<ApiClient>();
  AppState appState = injector.get<AppState>();

  @override
  Future<HubConnection> getHubConnection() async {
    final userId = AppState().getUser.data!.userInfo!.userId ?? "";
    final hubUrl = "${ApiConsts.signalRUrl}?userID=$userId";
    logger.i("Connecting with Hub ($hubUrl)");

    HubConnection hub;
    hub = HubConnectionBuilder()
        .withUrl(
            hubUrl,
            HttpConnectionOptions(
              client: IOClient(HttpClient()..badCertificateCallback = (x, y, z) => true),
              logging: (level, message) {},
            ))
        .withAutomaticReconnect()
        .build();
    return hub;
  }

  @override
  Future<bool> markMessageAsRead({required List<int> messageIds, required ChatTypeEnum chatTypeEnum}) async {
    String url = "";

    if (chatTypeEnum == ChatTypeEnum.ads) {
      url = ApiConsts.messageIsReadUpdateForAds;
    } else if (chatTypeEnum == ChatTypeEnum.requestOffer) {
      url = ApiConsts.messageIsReadUpdateForRequests;
    } else if (chatTypeEnum == ChatTypeEnum.general) {
      url = ApiConsts.messageIsReadUpdateForRequests;
    }
    var queryParameters = {"iDs": messageIds};
    GenericRespModel genericRespModel = await apiClient.postJsonForObject(
      (json) => GenericRespModel.fromJson(json),
      url,
      queryParameters,
      token: appState.getUser.data!.accessToken,
    );

    return genericRespModel.message == "";
  }

  @override
  Future<List<ChatMessageModel>> getUsersChatMessagesForRequests({
    required int providerId,
    required int customerId,
    required int requestOfferId,
    required int requestId,
    int pageIndex = 0,
    int pageSize = 0,
  }) async {
    var queryParameters = {
      "ReqOfferID": requestOfferId.toString(),
      "RequestID": requestId.toString(),
      "ProviderID": providerId.toString(),
      "CustomerID": customerId.toString(),
      "PageSize": pageSize.toString(),
      "PageIndex": pageIndex.toString(),
    };
    GenericRespModel genericRespModel = await apiClient.getJsonForObject(
      (json) => GenericRespModel.fromJson(json),
      ApiConsts.getChatMessagesForRequests,
      queryParameters: queryParameters,
      token: appState.getUser.data!.accessToken,
    );
    if (genericRespModel.messageStatus == 1 && genericRespModel.data != null) {
      List<ChatMessageModel> chatMessages = List.generate(
        genericRespModel.data.length,
        (index) => ChatMessageModel.fromJson(genericRespModel.data[index]),
      );
      return chatMessages;
    }
    return [];
  }

  @override
  Future<List<ChatMessageModel>> getUsersChatMessagesForAds({String? userID, int? adID, int? adsChatBuyerId, required bool isForBuyer, int pageIndex = 0, int pageSize = 0}) async {
    var parameterForBuyer = {
      "UserID": userID.toString(),
      "AdsID": adID.toString(),
      "IsAdsBuyer": isForBuyer.toString(),
      "PageSize": pageSize.toString(),
      "PageIndex": pageIndex.toString(),
    };

    var parameterForSeller = {
      "AdsChatBuyerID": adsChatBuyerId.toString(),
      "IsAdsBuyer": isForBuyer.toString(),
      "PageSize": pageSize.toString(),
      "PageIndex": pageIndex.toString(),
    };

    var queryParameters = isForBuyer ? parameterForBuyer : parameterForSeller;
    GenericRespModel genericRespModel = await apiClient.getJsonForObject(
      (json) => GenericRespModel.fromJson(json),
      ApiConsts.getChatMessagesForAds,
      queryParameters: queryParameters,
      token: appState.getUser.data!.accessToken,
    );
    if (genericRespModel.messageStatus == 1 && genericRespModel.data != null) {
      List<ChatMessageModel> chatMessages = List.generate(
        genericRespModel.data.length,
        (index) => ChatMessageModel.fromJson(genericRespModel.data[index]),
      );
      return chatMessages;
    }
    return [];
  }

  @override
  Future<List<ChatMessageModel>> getUsersChatMessagesForGeneralChat({String? userID, int? adID, int? adsChatBuyerId, required bool isForBuyer, int pageIndex = 0, int pageSize = 0}) async {
    var parameterForBuyer = {
      "UserID": userID.toString(),
      "AdsID": adID.toString(),
      "IsAdsBuyer": isForBuyer.toString(),
      "PageSize": pageSize.toString(),
      "PageIndex": pageIndex.toString(),
    };

    var parameterForSeller = {
      "AdsChatBuyerID": adsChatBuyerId.toString(),
      "IsAdsBuyer": isForBuyer.toString(),
      "PageSize": pageSize.toString(),
      "PageIndex": pageIndex.toString(),
    };

    var queryParameters = isForBuyer ? parameterForBuyer : parameterForSeller;
    GenericRespModel genericRespModel = await apiClient.getJsonForObject(
      (json) => GenericRespModel.fromJson(json),
      ApiConsts.getChatMessagesForAds,
      queryParameters: queryParameters,
      token: appState.getUser.data!.accessToken,
    );
    if (genericRespModel.messageStatus == 1 && genericRespModel.data != null) {
      List<ChatMessageModel> chatMessages = List.generate(
        genericRespModel.data.length,
        (index) => ChatMessageModel.fromJson(genericRespModel.data[index]),
      );
      return chatMessages;
    }
    return [];
  }
}
