import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:injectable/injectable.dart';
import 'package:keyboard/base/base_controller.dart';
import 'package:keyboard/data/bean/character_info.dart';
import 'package:keyboard/data/repository/account_repository.dart';
import 'package:keyboard/data/repository/keyboard_repository.dart';
import 'package:keyboard/dialog/character_add_dialog.dart';
import 'package:keyboard/dialog/custom_character/custom_character_add_dialog.dart';
import 'package:keyboard/dialog/login/login_dialog.dart';
import 'package:keyboard/module/character/content/character_group_content_controller.dart';
import 'package:keyboard/resource/string.gen.dart';
import 'package:keyboard/utils/atmob_log.dart';
import 'package:keyboard/utils/toast_util.dart';

import '../../data/bean/keyboard_info.dart';
import '../../data/consts/error_code.dart';
import '../../plugins/keyboard_android_platform.dart';
import '../../utils/error_handler.dart';
import '../../utils/http_handler.dart';

enum KeyboardType {
  system, //通用键盘
  custom, //自定义键盘
}

@injectable
class KeyboardManageController extends BaseController
    with GetTickerProviderStateMixin {
  final String tag = 'KeyboardManageController';

  final AccountRepository accountRepository;

  bool get isLogin => accountRepository.isLogin.value;

  // 自定义键盘列表
  final RxList<KeyboardInfo> _customKeyboardInfoList = RxList();

  List<KeyboardInfo> get customKeyboardInfoList => _customKeyboardInfoList;

  // 当前自定义键盘
  final Rx<KeyboardInfo> _currentCustomKeyboardInfo = KeyboardInfo().obs;

  KeyboardInfo get currentCustomKeyboardInfo =>
      _currentCustomKeyboardInfo.value;

  //当前自定义键盘人设列表
  final RxList<CharacterInfo> _currentCustomKeyboardCharacterList = RxList();

  RxList<CharacterInfo> get currentCustomKeyboardCharacterList =>
      _currentCustomKeyboardCharacterList;

  // 当前自定义键盘亲密度
  final RxInt _currentCustomIntimacy = 0.obs;

  int get currentCustomIntimacy => _currentCustomIntimacy.value;

  // 当前定制亲密度是否有变化
  final RxBool _customIntimacyChanged = false.obs;

  bool get customIntimacyChanged => _customIntimacyChanged.value;

  final RxBool _customKeyboardCharacterListChanged = false.obs;

  bool get customKeyboardCharacterListChanged =>
      _customKeyboardCharacterListChanged.value;

  // 存储排序前的定制人设列表,用于比较是否有变化
  List<CharacterInfo> _oldCustomCharacterList = [];

  // 通用键盘列表
  final RxList<KeyboardInfo> _generalKeyboardInfoList = RxList();

  List<KeyboardInfo> get generalKeyboardInfoList => _generalKeyboardInfoList;

  // 当前通用键盘
  final Rx<KeyboardInfo> _currentGeneralKeyboardInfo = KeyboardInfo().obs;

  KeyboardInfo get currentGeneralKeyboardInfo =>
      _currentGeneralKeyboardInfo.value;

  // 当前通用键盘人设列表
  final RxList<CharacterInfo> _currentGeneralKeyboardCharacterList = RxList();

  List<CharacterInfo> get currentGeneralKeyboardCharacterList =>
      _currentGeneralKeyboardCharacterList;

  // 当前通用键盘亲密度
  final RxInt _currentGeneralIntimacy = 0.obs;

  int get currentGeneralIntimacy => _currentGeneralIntimacy.value;

  // 当前通用亲密度是否有变化
  final RxBool _generalIntimacyChanged = false.obs;

  RxBool get generalIntimacyChanged => _generalIntimacyChanged;

  final RxBool _generalKeyboardCharacterListChanged = false.obs;

  bool get generalKeyboardCharacterListChanged =>
      _generalKeyboardCharacterListChanged.value;

  // 存储排序前的通用人设列表,用于比较是否有变化
  late List<CharacterInfo> _oldGeneralCharacterList;

  final KeyboardRepository keyboardRepository;

  // 最小人设数量
  final _minCount = 9;

  // 键盘管理类型
  List<String> keyboardManageType = [
    StringName.keyboardCustom,
    StringName.generalKeyboard,
  ];

  // 键盘管理页面的tabController，用于控制通用键盘和自定义键盘的切换
  late TabController tabController;

  // 键盘管理页面的pageController，用于控制通用键盘和自定义键盘的切换
  late PageController pageController;

  // 首次加载数据标志
  final isFirstLoad = true.obs;

  KeyboardManageController(this.keyboardRepository, this.accountRepository);

  @override
  void onInit() async {
    super.onInit();

    final args = Get.arguments;
    if (args is Map && args["customKeyboardInfo"] is KeyboardInfo) {
      _currentCustomKeyboardInfo.value = args["customKeyboardInfo"];
    }

   await _dataLoad();
  }

  _dataLoad() async {
    tabController = TabController(
      length: keyboardManageType.length,
      vsync: this,
      initialIndex: 0,
    );
    tabController.addListener(() {
      if (tabController.indexIsChanging) {
        switchTabKeyboardType(tabController.index);
      }
    });

    pageController = PageController();

    await getCustomKeyboard();
    if (isFirstLoad.value) {
      if (_customKeyboardInfoList.isEmpty) {
        //   去另一个tab
        pageController.jumpToPage(1);
      }

      isFirstLoad.value = false;
    }

    getGeneralKeyboard();
  }

  clickBack() {
    AtmobLog.i(tag, 'clickBack');
    Get.back();
  }

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

  //   获取定制键盘
  Future<void> getCustomKeyboard() async {
    AtmobLog.i(tag, 'getCustomKeyboard');
   await keyboardRepository.getKeyboardList(type: KeyboardType.custom.name).then((
      keyboardListResponse,
    ) {
      AtmobLog.i(
        tag,
        'keyboardListResponse: ${keyboardListResponse.keyboardInfos}',
      );
      _customKeyboardInfoList.value = keyboardListResponse.keyboardInfos;

      //检查是否是选择的键盘，如果没有选择的键盘，默认选择第一个
      if (_customKeyboardInfoList.isNotEmpty) {
        if (_currentCustomKeyboardInfo.value.id == null) {
          _currentCustomKeyboardInfo.value = _customKeyboardInfoList.firstWhere(
            (element) => element.isChoose == true,
            orElse: () => _customKeyboardInfoList.first,
          );
        }
        _currentCustomIntimacy.value =
            _currentCustomKeyboardInfo.value.intimacy ?? 0;
        _currentCustomIntimacy.listen((intimacy) {
          _customIntimacyChanged.value =
              _currentCustomKeyboardInfo.value.intimacy != intimacy;
          AtmobLog.d(tag, 'intimacyChanged: $_customIntimacyChanged');
        });

        String? id = _currentCustomKeyboardInfo.value.id;
        if (id != null) {
          getKeyboardCharacterList(keyboardId: id, isCustom: true);
        }
      }
    });
  }

  //   获取通用键盘
  void getGeneralKeyboard() {
    AtmobLog.i(tag, 'getGeneralKeyboard');
    keyboardRepository.getKeyboardList(type: KeyboardType.system.name).then((
      keyboardListResponse,
    ) {
      AtmobLog.i(
        tag,
        'keyboardListResponse: ${keyboardListResponse.keyboardInfos}',
      );
      _generalKeyboardInfoList.value = keyboardListResponse.keyboardInfos;
      _currentGeneralKeyboardInfo.value = _generalKeyboardInfoList.first;
      _currentGeneralIntimacy.value =
          _currentGeneralKeyboardInfo.value.intimacy ?? 0;
      _currentGeneralIntimacy.listen((intimacy) {
        _generalIntimacyChanged.value =
            _currentGeneralKeyboardInfo.value.intimacy != intimacy;
        AtmobLog.d(tag, 'intimacyChanged: $_generalIntimacyChanged');
      });

      String? id = _currentGeneralKeyboardInfo.value.id;
      if (id != null) {
        getKeyboardCharacterList(keyboardId: id, isCustom: false);
      }
    });
  }

  // 获取当前键盘人设列表
  void getKeyboardCharacterList({
    required String keyboardId,
    required bool isCustom,
  }) {
    if (isCustom) {
      keyboardRepository.getKeyboardCharacterList(keyboardId: keyboardId).then((
        keyboardCharacterListResponse,
      ) {
        AtmobLog.i(
          tag,
          'keyboardCharacterListResponse: ${keyboardCharacterListResponse.characterInfos.toString()}',
        );
        _currentCustomKeyboardCharacterList.assignAll(
          keyboardCharacterListResponse.characterInfos,
        );
        _oldCustomCharacterList = List<CharacterInfo>.from(
          _currentCustomKeyboardCharacterList,
        );
        _customKeyboardCharacterListChanged.value = false;
        _currentCustomKeyboardCharacterList.listen((event) {
          _customKeyboardCharacterListChanged.value =
              !ListEquality().equals(_oldCustomCharacterList, event);
          AtmobLog.d(
            tag,
            '_customKeyboardCharacterListChanged: $_customKeyboardCharacterListChanged',
          );
        });
      });
    } else {
      keyboardRepository.getKeyboardCharacterList(keyboardId: keyboardId).then((
        keyboardCharacterListResponse,
      ) {
        AtmobLog.i(
          tag,
          'keyboardCharacterListResponse: ${keyboardCharacterListResponse.characterInfos.toString()}',
        );
        if (_currentGeneralKeyboardInfo.value.id == keyboardId) {
          _currentGeneralKeyboardCharacterList.value =
              keyboardCharacterListResponse.characterInfos;
          _oldGeneralCharacterList = List<CharacterInfo>.from(
            _currentGeneralKeyboardCharacterList,
          );
          _generalKeyboardCharacterListChanged.value = false;
          _currentGeneralKeyboardCharacterList.listen((event) {
            _generalKeyboardCharacterListChanged.value =
                !ListEquality().equals(_oldGeneralCharacterList, event);
            AtmobLog.d(
              tag,
              '_generalKeyboardCharacterListChanged: $_generalKeyboardCharacterListChanged',
            );
          });
        }
        if (_currentCustomKeyboardInfo.value.id == keyboardId) {
          _currentCustomKeyboardCharacterList.value =
              keyboardCharacterListResponse.characterInfos;
        }
      });
    }
  }

  //   切换当前定制键盘
  void switchCustomKeyboard(String? keyboardName) {
    _currentCustomKeyboardInfo.value = _customKeyboardInfoList.firstWhere(
      (element) => element.name == keyboardName,
      orElse: () => _customKeyboardInfoList.first,
    );
    String? keyboardId = _currentCustomKeyboardInfo.value.id;
    _currentCustomIntimacy.value =
        _currentCustomKeyboardInfo.value.intimacy ?? 0;
    if (keyboardId != null) {
      getKeyboardCharacterList(keyboardId: keyboardId, isCustom: true);
    }
  }

  // tab切换
  void switchTabKeyboardType(int index) {
    // AtmobLog.i(tag, 'onTabChanged: $index');
    pageController.animateToPage(
      index,
      duration: const Duration(milliseconds: 300),
      curve: Curves.easeInToLinear,
    );
  }

  // page切换
  void switchPageKeyboardType(int index) {
    // AtmobLog.i(tag, 'onPageChanged: $index');

    tabController.animateTo(index, duration: const Duration(milliseconds: 300));

    if (index == 0) {
      _currentGeneralIntimacy.value =
          _currentGeneralKeyboardInfo.value.intimacy ?? 0;
      _currentGeneralKeyboardCharacterList.value = _oldGeneralCharacterList;
      _generalIntimacyChanged.value = false;
      _generalKeyboardCharacterListChanged.value = false;
      getCustomKeyboard();
    } else {
      _currentCustomIntimacy.value =
          _currentCustomKeyboardInfo.value.intimacy ?? 0;

      if (_oldCustomCharacterList.isNotEmpty) {
        _currentCustomKeyboardCharacterList.value = _oldCustomCharacterList;
      }

      _customIntimacyChanged.value = false;
      _customKeyboardCharacterListChanged.value = false;
      getGeneralKeyboard();
    }
  }

  // 更新亲密度
  void updateIntimacy(int intimacy, bool isCustom) {
    if (isCustom) {
      _currentCustomIntimacy.value = intimacy;
    } else {
      _currentGeneralIntimacy.value = intimacy;
    }
  }

  // 排序
  void onReorder(int oldIndex, int newIndex, bool isCustom) {
    if (isCustom) {
      reorderList(_currentCustomKeyboardCharacterList, oldIndex, newIndex);
    } else {
      reorderList(_currentGeneralKeyboardCharacterList, oldIndex, newIndex);
    }
  }

  // 排序
  void reorderList<T>(RxList<T> list, int oldIndex, int newIndex) {
    AtmobLog.d(tag, 'reorderList: $oldIndex, $newIndex');
    final item = list.removeAt(oldIndex);
    list.insert(newIndex, item);
  }

  void clickSave(bool isCustom) {
    isCustom
        ? saveCustomKeyboardCharacterList()
        : saveGeneralKeyboardCharacterList();
  }

  void saveCustomKeyboardCharacterList() {
    _saveKeyboardInfo(
      intimacyChanged: _customIntimacyChanged,
      currentIntimacy: currentCustomIntimacy,
      currentKeyboardInfo: _currentCustomKeyboardInfo,
      characterListChanged: _customKeyboardCharacterListChanged,
      currentCharacterList: _currentCustomKeyboardCharacterList,
      onUpdateSuccess: () {
        _oldCustomCharacterList = List<CharacterInfo>.from(
          _currentCustomKeyboardCharacterList,
        );
        Get.find<CharacterGroupContentController>().refreshData();
        // 通知键盘,刷新人设列表
        KeyboardAndroidPlatform.refreshCharacterList();
        saveSuccessGetBack();
      },
    );
  }

  void saveGeneralKeyboardCharacterList() {
    _saveKeyboardInfo(
      intimacyChanged: _generalIntimacyChanged,
      currentIntimacy: currentGeneralIntimacy,
      currentKeyboardInfo: _currentGeneralKeyboardInfo,
      characterListChanged: _generalKeyboardCharacterListChanged,
      currentCharacterList: _currentGeneralKeyboardCharacterList,
      onUpdateSuccess: () {
        _oldGeneralCharacterList = List<CharacterInfo>.from(
          _currentGeneralKeyboardCharacterList,
        );
        // 通知键盘,刷新人设列表
        KeyboardAndroidPlatform.refreshCharacterList();
      },
    );
  }

  void _saveKeyboardInfo({
    required RxBool intimacyChanged,
    required int currentIntimacy,
    required Rx<KeyboardInfo> currentKeyboardInfo,
    required RxBool characterListChanged,
    required List<CharacterInfo> currentCharacterList,
    required VoidCallback onUpdateSuccess,
  }) {
    String? keyboardId = currentKeyboardInfo.value.id;

    if (intimacyChanged.value && keyboardId != null) {
      AtmobLog.i(tag, 'clickSave intimacyChanged');
      currentKeyboardInfo.value.intimacy = currentIntimacy;
      keyboardRepository
          .updateKeyboardInfo(keyboardId: keyboardId, intimacy: currentIntimacy)
          .then((_) async {
            ToastUtil.show(StringName.keyboardSaveSuccess);
            await keyboardRepository.refreshData();
          })
          .catchError((error) {
            if (error is ServerErrorException) {
              ErrorHandler.toastError(error);
              if (error.code == ErrorCode.noLoginError) {
                LoginDialog.show();
              }
            } else {
              ToastUtil.show(StringName.keyboardSaveFailed);
            }
          })
          .whenComplete(() => intimacyChanged.value = false);
    }

    if (characterListChanged.value && keyboardId != null) {
      AtmobLog.i(tag, 'clickSave keyboardChanged');
      List<String> characterIds =
          currentCharacterList.map((e) => e.id).cast<String>().toList();
      keyboardRepository
          .keyboardCharacterUpdate(
            keyboardId: keyboardId,
            characterIds: characterIds,
          )
          .then((_) async {
            onUpdateSuccess();
            ToastUtil.show(StringName.keyboardSaveSuccess);
            await keyboardRepository.refreshData();
          })
          .catchError((error) {
            if (error is ServerErrorException) {
              ErrorHandler.toastError(error);
              if (error.code == ErrorCode.noLoginError) {
                LoginDialog.show();
              }
            } else {
              ToastUtil.show(StringName.keyboardSaveFailed);
            }
          })
          .whenComplete(() => characterListChanged.value = false);
    }
  }

  void clickRemoveCharacter(CharacterInfo characterInfo, bool isCustom) {
    if (isCustom) {
      if (_currentCustomKeyboardCharacterList.length <= _minCount) {
        ToastUtil.show("最少需要保持$_minCount个人设");
        return;
      }
      AtmobLog.i(tag, 'clickRemoveCharacter');
      _currentCustomKeyboardCharacterList.remove(characterInfo);
    } else {
      if (_currentGeneralKeyboardCharacterList.length <= _minCount) {
        ToastUtil.show("最少需要保持$_minCount个人设");
        return;
      }
      AtmobLog.i(tag, 'clickRemoveCharacter');

      _currentGeneralKeyboardCharacterList.remove(characterInfo);
    }
  }

  clickAddCharacter({required bool isCustom}) {
    if (!isLogin) {
      ToastUtil.show("请先登录");
      LoginDialog.show();
      return;
    }
    if (isCustom) {
      CharacterAddDialog.show(
        currentKeyboardInfo: currentCustomKeyboardInfo,
        clickCallback: () {
          getKeyboardCharacterList(
            keyboardId: _currentCustomKeyboardInfo.value.id ?? "",
            isCustom: true,
          );
        },
      );
    } else {
      CharacterAddDialog.show(
        currentKeyboardInfo: currentGeneralKeyboardInfo,
        clickCallback: () {
          getGeneralKeyboard();
        },
      );
    }
  }

  clickCustomCharacter() {
    if (!isLogin) {
      ToastUtil.show("请先登录");
      LoginDialog.show();
      return;
    }
    AtmobLog.i(tag, 'clickCustomCharacter');
    CustomCharacterAddDialog.show(
      currentKeyboardInfo: currentCustomKeyboardInfo,
      clickCallback: () {
        getKeyboardCharacterList(
          keyboardId: _currentCustomKeyboardInfo.value.id ?? "",
          isCustom: true,
        );
      },
    );
  }

  @override
  void onClose() {
    tabController.dispose();
    pageController.dispose();
    super.onClose();
  }

  void saveSuccessGetBack() {
    Get.back(result: _currentCustomKeyboardCharacterList);
  }
}
