import 'dart:async';

import 'package:electronic_assistant/base/app_base_request.dart';
import 'package:electronic_assistant/data/api/atmob_api.dart';
import 'package:electronic_assistant/data/bean/member_info.dart';
import 'package:electronic_assistant/data/repositories/task_repository.dart';
import 'package:electronic_assistant/utils/async_util.dart';
import 'package:electronic_assistant/utils/cancel_future.dart';
import 'package:electronic_assistant/utils/event_bus.dart';
import 'package:electronic_assistant/utils/mmkv_util.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';

import '../../resource/string.gen.dart';
import '../../utils/http_handler.dart';
import '../api/request/login_request.dart';
import '../api/request/user_info_update_request.dart';
import '../api/request/verification_code_request.dart';
import '../api/response/login_response.dart';
import '../api/response/user_info_response.dart';
import '../consts/error_code.dart';

const String EventUserLogin = 'EventUserLogin';
const String EventUserLogout = 'EventUserLogout';

class AccountRepository {
  final ACCOUNT_TOKEN = 'account_token';
  final ACCOUNT_PHONE = 'account_phone';

  String? _token;
  String? _phone;
  final isLogin = false.obs;

  UserInfoResponse? _userInfo;

  CancelableFuture? _getUserInfoFuture;

  AccountRepository._() {
    debugPrint('AccountRepository init');
    _token = KVUtil.getString(ACCOUNT_TOKEN, null);
    _phone = KVUtil.getString(ACCOUNT_PHONE, null);
    if (_token != null && _token!.isNotEmpty) {
      isLogin.value = true;
      Future.delayed(Duration.zero, () {
        refreshUserInfo();
        taskRepository.startUnfinishedTask();
      });
    }
  }

  UserInfoResponse? get userInfo => _userInfo;

  String? get phone => _phone;

  String? get token => _token;

  Future<void> getVerificationCode(String phone) {
    return atmobApi
        .getVerificationCode(VerificationCodeRequest(phone))
        .then(HttpHandler.handle(true));
  }

  Future<void> userDeprecate() {
    return atmobApi
        .userDeprecate(AppBaseRequest())
        .then(HttpHandler.handle(true));
  }

  Future<void> updateUserInfo(String profession, String post) {
    return atmobApi
        .updateUserInfo(UserInfoUpdateRequest(profession, post))
        .then(HttpHandler.handle(true))
        .then((data) {
      accountRepository.refreshUserInfo();
    });
  }

  Future<void>? refreshUserInfo() {
    if (_getUserInfoFuture != null) {
      _getUserInfoFuture?.cancel();
    }
    _getUserInfoFuture = AsyncUtil.retryWithExponentialBackoff(
        () => _getUserInfo(), 10, (error) {
      if (error is ServerErrorException) {
        return error.code != ErrorCode.errorCodeNoLogin;
      }
      return true;
    });
    return _getUserInfoFuture;
  }

  Future<UserInfoResponse> _getUserInfo() {
    return atmobApi
        .userInfo(AppBaseRequest())
        .then(HttpHandler.handle(false))
        .then((response) {
      _userInfo = response;
      return response;
    });
  }

  Future<LoginResponse> login(String phone, String code) {
    return atmobApi
        .login(LoginRequest(phone, code))
        .then(HttpHandler.handle(false))
        .then((response) {
      onLoginSuccess(phone, response.authToken);
      return response;
    });
  }

  void onLoginSuccess(String phone, String? token) {
    _token = token;
    _phone = phone;
    KVUtil.putString(ACCOUNT_TOKEN, token);
    KVUtil.putString(ACCOUNT_PHONE, phone);
    isLogin.value = true;
    refreshUserInfo();
    taskRepository.startUnfinishedTask();

    eventBus.emit(EventUserLogin);
  }

  void logout() {
    _phone = null;
    _token = null;
    KVUtil.putString(ACCOUNT_TOKEN, null);
    KVUtil.putString(ACCOUNT_PHONE, null);
    isLogin.value = false;
    taskRepository.stopTask();
    _userInfo = null;

    eventBus.emit(EventUserLogout);
  }

  getUserSubName(String? phone) {
    String name = StringName.account.tr;
    if (phone == null) {
      return name;
    }
    //后4位
    if (phone.length > 4) {
      phone = phone.substring(phone.length - 4);
    }
    return '$name$phone';
  }
}

final accountRepository = AccountRepository._();
