import 'package:fis_common/helpers/encrypt.dart';
import 'package:fis_common/index.dart';
import 'package:fis_i18n/i18n.dart';
import 'package:fis_ui/index.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flyinsono/architecture/define.dart';
import 'package:fis_common/logger/logger.dart';
import 'package:fis_jsonrpc/services/index.dart';
import 'package:flyinsono/architecture/router/index.dart';
import 'package:flyinsono/architecture/services/modules/config_language.dart';
import 'package:flyinsono/js_platform/listener.dart';
import 'package:flyinsono/managers/interfaces/vboxcontrol.dart';
import 'package:flyinsono/pages/index.dart';
import 'package:flyinsono/pages/upgrade/upgrade_widgets/upgrade_center.dart';
import 'package:flyinsono/pages/upgrade/upgrade_wrapper.dart';
import 'package:flyinsono/pages/user/user_center/widgets/change_password_page.dart';
import 'package:flyinsono/rpc.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/architecture/utils/prompt_box.dart';
import 'package:get/get.dart';
import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart';
import '../auth_board/controller.dart';
import 'state.dart';
import 'package:fis_jsonrpc/exception.dart';

class SignInController extends FControllerBase
    with GetSingleTickerProviderStateMixin {
  static const C_VERIFICATION_CONTROLLER_TAG = "sign_in";

  final state = SignInState();
  final _debouncer = Debouncer(delay: Duration(milliseconds: 400));

  /// 语言包初始化
  final languageService = Get.find<LanguageService>();

  /// 文本编辑器
  final verificationCodeController = TextEditingController();
  final accountController = TextEditingController();

  /// 密码框文本编辑器
  final passwordController = TextEditingController();

  /// 文本焦点
  final accountFocusNode = FocusNode();
  final pwdFocusNode = FocusNode();
  final codeAccountFocusNode = FocusNode();
  final verificationCodeFocusNode = FocusNode();

  /// tab选择器
  late TabController tabController;

  /// 标签页列表
  List<String> get tabTitles => [
        i18nBook.auth.tabOfLoginByAccountPwd.t,
        i18nBook.auth.tabOfLoginByVerificationCode.t,
      ];

  /// 当前平台
  Platform get platform => FPlatform.isAndroid
      ? Platform.Android
      : FPlatform.isIOS
          ? Platform.Ios
          : Platform.Windows;

  /// 当前设备
  LoginSource get loginSource => kIsMobile
      ? LoginSource.Mobile
      : FPlatform.isPureWeb
          ? LoginSource.Web
          : (FPlatform.isMacOS || FPlatform.isWindows)
              ? LoginSource.PC
              : LoginSource.Pad;

  /// 事件

  /// 切换登录方式
  void onTabChanged(int index) {
    SignInMethod method = SignInMethod.values[index];
    state.signInMethod = method;
  }

  /// 记住密码状态切换
  void onRememberPasswordChanged(bool val) {
    state.isAutoLogin = val;
  }

  /// 条款选择框切换
  void onAgreeClauseChanged(bool val) {
    state.isAgreeClause = val;
  }

  /// 接收外部参数
  void acceptParameters(Map<String, String?> parameters) {
    if (parameters.containsKey("signup_account")) {
      state.account = parameters['signup_account'] ?? "";
      state.password = "";
      passwordController.text = "";
    }
  }

  /// 处理登录
  Future<void> onSignInSubmit() async {
    if (CartSystemPlatform.isCartSystemVersion) {
      var vBoxManager = Get.find<IVBoxControlManager>();
      vBoxManager.canShowHardwareDetector = true;
    }
    _debouncer.call(() async {
      if (UpgradeCenter.isChecking) {
        Get.back();
        UpgradeCenter.isChecking = false;
      }
      if (!state.isCanSubmit) return;

      final formValidMsg = _validateForm();
      if (formValidMsg != null) {
        return PromptBox.toast(formValidMsg);
      }
      state.onSubmit = true;

      var account = '';
      var userAccout = state.isCodeSignIn ? state.codeAccount : state.account;
      final password = state.isCodeSignIn ? "" : state.password;
      final code = state.isCodeSignIn ? state.verificationCode : "";
      account = userAccout;
      try {
        logger.i("User - [$account] start login");
        final result = await rpc.login.commonLoginAsync(
          CommonLoginRequest(
            anyAccount: account.trim(),
            anyCode: code,
            password: password.isEmpty
                ? ''
                : FEncryptHelper.symmetryEncrypt(password),
            platform: platform,
            loginSource: loginSource,
            languageCode: i18nBook.locale.languageCode,
          ),
        );

        /// 密码输错之后 错误提示
        if (result.lockRemainingTimes != null) {
          await passwordRetryPrompt(result.lockRemainingTimes!);
        }
        logger.i("User - [$account] logon! Session Token: ${result.token}.");
        if (result.token != null && result.token!.isNotEmpty) {
          Store.user.setToken(result.token!);
          await handleSignIn(result);

          /// 三月之后的密码过期 选择是否重设密码
          if (result.passwordExpired) {
            await passwordFailureReset();
          } else {
            _successfulLoginNavigation();
          }
        }
      } on JsonRpcNetworkException catch (_) {
        PromptBox.toast(i18nBook.auth.toast4LoginFailNetworkIssues.t);
      } catch (e) {
        logger.e("Login failed.", e);
      }

      state.onSubmit = false;
    });
  }

  /// 密码失效机制 修改密码
  Future<void> passwordFailureReset() async {
    JsListener businessParent = JsListener();
    FConfirmAlert.show(
      context: Get.context!,
      title: i18nBook.auth.theCurrentPasswordHasExpired.t,
      subTitle: i18nBook.auth.confirmEnterOrResetPassword.t,
      businessParent: businessParent,
      confrimLabel: i18nBook.auth.resetPassword.t,
      cancelLabel: i18nBook.auth.confirmEnter.t,
      onConfirm: () async {
        await router.dialog(
          () => ChangePasswordPage(),
          binding: UserCenterBinding(),
        );
        Store.user.handelLogOut();
        passwordController.text = "";
      },
      onCancel: () {
        _successfulLoginNavigation();
      },
    );
  }

  /// 密码重试机制
  Future<void> passwordRetryPrompt(int lockRemainingTimes) async {
    return PromptBox.toast(
      i18nBook.auth.remainingTimes.translate(
        [lockRemainingTimes],
      ),
    );
  }

  /// 处理登录
  Future<void> handleSignIn(LoginResult result) async {
    try {
      final userInfo = await rpc.user.getUserInfoAsync(GetUserInfoRequest(
        token: result.token,
      ));
      Store.user.avatar = userInfo.headImageUrl ?? "";
      Store.user.setBatchExportRight(userInfo.isBatchExportDiagnoseData);
      Store.user.handleUserSyncUpdate(userInfo);
      state.userCode = userInfo.userCode!;
      await _saveSignInState(result).then(
        (value) => languageService.init(),
      );
    } catch (e) {
      logger.e("handleSignIn failed.", e);
    }
  }

  /// 注册
  Future<void> onSignUpClick() async {
    Get.find<AuthBoardController>().changePageByName(RouteNames.Auth.SignUp);
  }

  /// 忘记密码
  Future<void> onRetrievePasswordClick() async {
    Get.find<AuthBoardController>()
        .changePageByName(RouteNames.Auth.RetrievePwd);
  }

  /// 网络设置
  Future<void> onNetworkSettingClick() async {
    await router.dialog(
      () => ServerSettingPage(),
      binding: ServerSettingBinding(),
    );
  }

  /// 获取验证码
  Future<bool> onFetchCode() async {
    final account = state.codeAccount;
    bool canSend = false;
    //var ads = rpc.upgrade.getUpgradeInfoAsync(new GetUpgradeInfoRequest());
    if (account.isNotEmpty) {
      if (i18nBook.isCurrentChinese) {
        canSend = account.isEmail || account.isChineseMobileNumber;
      } else {
        canSend = account.isEmail;
      }
    }
    if (!canSend) {
      PromptBox.toast(i18nBook.auth.toast4AccountDouble.t);
      return false;
    }

    setBusy(i18nBook.auth.sendingVerificationCode.t);
    bool valid = false;
    final isMobileAccount = account.isChineseMobileNumber;
    try {
      if (isMobileAccount) {
        valid = await rpc.login.sendSMSVerificationCodeAsync(
          SendSMSVerificationCodeRequest(userPhone: account),
        );
      } else {
        valid = await rpc.login.sendEmailVerificationCodeAsync(
          SendEmailVerificationCodeRequest(
            emailAddress: account,
            languageCode: i18nBook.locale.toCodeString('-'),
          ),
        );
      }
      if (valid) {
        PromptBox.toast(i18nBook.auth.toast4VerifyCodeSendSuccess.t);
        return true;
      }
    } catch (e) {
      logger.e(
          "Register: send ${isMobileAccount ? 'message' : 'email'} verify code error",
          e);
      PromptBox.toast(i18nBook.auth.toast4VerifyCodeSendFail.t);
    }
    busy = false;
    return false;
  }

  @override
  void onInit() async {
    tabController = TabController(
      vsync: this,
      length: tabTitles.length,
      initialIndex: SignInMethod.Account.index,
    );
    _loadStateHis();
    passwordController.text = state.password;
    super.onInit();
  }

  @override
  void onReady() {
    super.onReady();
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      if (Get.context != null) {
        UpgradeWrapper.invokeUpgradeDirectly(Get.context!, true);
      }
    });
  }

  @override
  void onClose() {
    accountFocusNode.dispose();
    pwdFocusNode.dispose();
    codeAccountFocusNode.dispose();
    verificationCodeFocusNode.dispose();
    verificationCodeController.dispose();
    passwordController.dispose();
    tabController.dispose();
    super.onClose();
  }

  /// 加载历史状态
  void _loadStateHis() {
    state.account = Store.user.account ?? "";
    if (Store.user.isAgreeClause) {
      state.isAgreeClause = true;
    }
    if (Store.user.isAutoLogin) {
      state.isAutoLogin = true;
      state.password = Store.user.password ?? "";
    }
  }

  /// 登录成功的跳转
  void _successfulLoginNavigation() {
    router.offAll(RouteNames.Home.Home);
  }

  /// 校验表单
  String? _validateForm() {
    bool isAgreeClause = state.isAgreeClause;
    if (kDebugMode) {
      //TODO:debug环境下默认同意条款和政策
      isAgreeClause = true;
    }
    if (!isAgreeClause) {
      logger.i("AgreeClause validation failed on submit sign in");
      return i18nBook.auth.toast4AgreeStatement.t;
    }
    if (state.isCodeSignIn) {
      final account = state.codeAccount;
      if (i18nBook.isCurrentChinese) {
        if (!account.isEmail && !account.isChineseMobileNumber) {
          return i18nBook.auth.toast4AccountDouble.t;
        }
      } else {
        // 英文不支持手机验证码
        if (!account.isEmail) {
          return i18nBook.auth.toast4AccountDouble.t;
        }
      }
    }

    return null;
  }

  /// 保存登录状态
  Future<void> _saveSignInState(LoginResult info) async {
    final isAutoLogin = state.isAutoLogin && !state.isCodeSignIn;
    await Store.user.handleLogOn(
      token: info.token!,
      code: state.userCode,
      isAutoLogin: isAutoLogin,
      isAgreeClause: state.isAgreeClause,
      password: state.password,
      account: state.account,
    );
    Store.user.handleAfterLogOn();
  }
}
