import 'package:flutter_openim_sdk/flutter_openim_sdk.dart';
import 'package:get/get.dart';
import 'package:openim/pages/contacts/group_profile_panel/group_profile_panel_logic.dart';
import 'package:openim/routes/app_navigator.dart';
import 'package:openim_common/openim_common.dart';

import '../../company/directory/directory_api.dart';
import '../../core/controller/im_controller.dart';
import '../home/home_logic.dart';
import 'select_contacts/select_contacts_logic.dart';

class ColleagueRow {
  ColleagueRow({
    required this.userID,
    required this.nickname,
    required this.faceURL,
    required this.department,
    required this.title,
  });

  final String userID;
  final String nickname;
  final String faceURL;
  final String department;
  final String title;

  String get subtitle {
    if (title.isNotEmpty && department.isNotEmpty) {
      return '$title · $department';
    }
    if (title.isNotEmpty) return title;
    return department;
  }
}

class ContactsLogic extends GetxController
    implements ViewUserProfileBridge, SelectContactsBridge, ScanBridge {
  final imLogic = Get.find<IMController>();
  final homeLogic = Get.find<HomeLogic>();
  final _directory = DirectoryApi();

  final friendApplicationList = <UserInfo>[];
  final loading = true.obs;
  final loadFailed = false.obs;
  final colleagues = <ColleagueRow>[].obs;

  int get friendApplicationCount =>
      homeLogic.unhandledFriendApplicationCount.value;

  int get groupApplicationCount =>
      homeLogic.unhandledGroupApplicationCount.value;

  Map<String, List<ColleagueRow>> get groupedColleagues {
    final map = <String, List<ColleagueRow>>{};
    for (final row in colleagues) {
      final key = row.department.isEmpty ? '未分组' : row.department;
      map.putIfAbsent(key, () => []).add(row);
    }
    final keys = map.keys.toList()
      ..sort((a, b) {
        if (a == '未分组') return 1;
        if (b == '未分组') return -1;
        return a.compareTo(b);
      });
    return {for (final k in keys) k: map[k]!};
  }

  @override
  void onInit() {
    PackageBridge.selectContactsBridge = this;
    PackageBridge.viewUserProfileBridge = this;
    PackageBridge.scanBridge = this;

    super.onInit();
  }

  @override
  void onReady() {
    reload();
    super.onReady();
  }

  Future<void> reload() async {
    loading.value = true;
    loadFailed.value = false;
    try {
      await Future.wait([
        OpenIM.iMManager.friendshipManager
            .getFriendApplicationListAsRecipient(),
        OpenIM.iMManager.groupManager.getGroupApplicationListAsRecipient(),
        _loadColleagues(),
      ]);
      homeLogic.getUnhandledFriendApplicationCount();
      homeLogic.getUnhandledGroupApplicationCount();
    } catch (e, s) {
      Logger.print('contacts reload e: $e $s');
      loadFailed.value = true;
    } finally {
      loading.value = false;
    }
  }

  Future<void> _loadColleagues() async {
    final friends = <FriendInfo>[];
    const page = 1000;
    while (true) {
      final temp = await OpenIM.iMManager.friendshipManager.getFriendListPage(
        offset: friends.length,
        count: page,
        filterBlack: true,
      );
      friends.addAll(temp);
      if (temp.length < page) break;
    }

    var dirById = <String, DirectoryUser>{};
    try {
      final items = await _directory.search(keyword: '', limit: 100);
      dirById = {for (final e in items) e.userID: e};
    } catch (e, s) {
      Logger.print('contacts directory e: $e $s');
    }

    colleagues.assignAll(friends.where((e) => e.userID != null).map((e) {
      final dir = dirById[e.userID];
      return ColleagueRow(
        userID: e.userID!,
        nickname: (e.remark?.isNotEmpty == true)
            ? e.remark!
            : (e.nickname?.isNotEmpty == true ? e.nickname! : e.userID!),
        faceURL: e.faceURL ?? dir?.faceURL ?? '',
        department: dir?.department ?? '',
        title: dir?.title ?? '',
      );
    }));
  }

  void openColleague(ColleagueRow row) => AppNavigator.startUserProfilePane(
        userID: row.userID,
        nickname: row.nickname,
        faceURL: row.faceURL,
      );

  @override
  void onClose() {
    PackageBridge.selectContactsBridge = null;
    PackageBridge.viewUserProfileBridge = null;
    PackageBridge.scanBridge = null;
    super.onClose();
  }

  void newFriend() => AppNavigator.startFriendRequests();

  void newGroup() => AppNavigator.startGroupRequests();

  void myFriend() => AppNavigator.startFriendList();

  void myGroup() => AppNavigator.startGroupList();

  void searchContacts() => AppNavigator.startGlobalSearch();

  void addContacts() => AppNavigator.startAddColleague();

  @override
  Future<T?>? selectContacts<T>(
    int type, {
    List<String>? defaultCheckedIDList,
    List? checkedList,
    List<String>? excludeIDList,
    bool openSelectedSheet = false,
    String? groupID,
    String? ex,
  }) =>
      AppNavigator.startSelectContacts(
        action: SelAction.values[type],
        defaultCheckedIDList: defaultCheckedIDList,
        checkedList: checkedList,
        excludeIDList: excludeIDList,
        openSelectedSheet: openSelectedSheet,
        groupID: groupID,
        ex: ex,
      );

  @override
  viewUserProfile(String userID, String? nickname, String? faceURL,
          [String? groupID]) =>
      AppNavigator.startUserProfilePane(
        userID: userID,
        nickname: nickname,
        faceURL: faceURL,
        groupID: groupID,
      );

  @override
  scanOutGroupID(String groupID) => AppNavigator.startGroupProfilePanel(
        groupID: groupID,
        joinGroupMethod: JoinGroupMethod.qrcode,
        offAndToNamed: true,
      );

  @override
  scanOutUserID(String userID) =>
      AppNavigator.startUserProfilePane(userID: userID, offAndToNamed: true);
}
