import 'dart:async';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_tool_android/flutter_tool_android.dart';
import 'package:get/get.dart';
import 'package:injectable/injectable.dart';
import 'package:location/base/base_controller.dart';
import 'package:location/data/bean/location_info.dart';
import 'package:location/data/bean/user_info.dart';
import 'package:location/data/consts/constants.dart';
import 'package:location/data/repositories/account_repository.dart';
import 'package:location/data/repositories/friends_repository.dart';
import 'package:location/data/repositories/message_repository.dart';
import 'package:location/handler/error_handler.dart';
import 'package:location/module/friend/friend_page.dart';
import 'package:location/module/login/login_page.dart';
import 'package:location/module/main/today_track_helper.dart';
import 'package:location/module/member/member_page.dart';
import 'package:location/module/news/news_page.dart';
import 'package:location/module/urgent_contact/urgent_contact_page.dart';
import 'package:location/resource/string.gen.dart';
import 'package:location/sdk/map/map_helper.dart';
import 'package:location/utils/mmkv_util.dart';
import 'package:location/utils/toast_util.dart';
import 'package:permission_handler/permission_handler.dart';
import '../../data/bean/member_status_info.dart';
import '../../data/repositories/config_repository.dart';
import '../../data/repositories/track_repository.dart';
import '../../data/repositories/urgent_contact_repository.dart';
import '../../dialog/check_loation_permission_dialog.dart';
import '../../dialog/common_alert_dialog_impl.dart';
import '../../dialog/common_confirm_dialog_impl.dart';
import '../../dialog/friend_dialog.dart';
import '../../dialog/location_permission_dialog.dart';
import '../../helper/internet_connection_helper.dart';
import '../../sdk/wechat/wechat_share_util.dart';
import '../../socket/atmob_location_client.dart';
import '../../utils/de_bounce.dart';
import '../../utils/location_convert_marker_util.dart';
import '../../utils/permission_util.dart';
import '../add_friend/add_friend_page.dart';
import '../mine/mine_page.dart';
import '../track/track_dialog/track_choose_friend_dialog.dart';
import '../track/track_dialog/track_daily_report_dialog.dart';
import '../track/track_page.dart';

@injectable
class MainController extends BaseController {
  RxList<UserInfo> get _friendsList => friendsRepository.friendsList;

  Rxn<MemberStatusInfo> get memberStatusInfo =>
      accountRepository.memberStatusInfo;

  RxList<UserInfo> integrateList = RxList();

  UserInfo get mineUserInfo => accountRepository.mineUserInfo.value;

  final Rxn<UserInfo> _selectedFriend = Rxn<UserInfo>();

  UserInfo? get selectedFriend => _selectedFriend.value;

  final MapController mapController = MapController();
  final MapController todayTrackSmallMapController = MapController();

  StreamSubscription? mineUserInfoSubscription;
  StreamSubscription? mineLocationSubscription;
  StreamSubscription? friendsListSubscription;
  StreamSubscription? loginSubscription;
  StreamSubscription? memberStatusInfoSubscription;

  bool isFirstShowMineLocation = true;
  DateTime _lastRefreshTime = DateTime.fromMillisecondsSinceEpoch(0);

  final FriendsRepository friendsRepository;
  final AccountRepository accountRepository;
  final MessageRepository messageRepository;
  final UrgentContactRepository urgentContactRepository;
  final TrackRepository trackRepository;
  final TodayTrackHelper todayTrackHelper;

  bool get hasUnreadMessage => messageRepository.hasUnreadMessage.value;

  DateTime? _lastPressedAt;
  DateTime? _lastRequestFavor;

  String? lastCheckFriendId;
  bool isExecuteAutoSelect = false;

  Timer? electricTimer;

  double? lastVisibleFraction;

  final Map<String, int> electricMap = {};

  RxMap<String, TodayTrackReportBean> get todayTrackReportMap =>
      todayTrackHelper.todayTrackReportMap;

  MainController(
      this.friendsRepository,
      this.accountRepository,
      this.messageRepository,
      this.todayTrackHelper,
      AtmobLocationClient atmobLocationClient,
      this.urgentContactRepository,
      ConfigRepository configRepository,
      this.trackRepository);

  @override
  void onReady() {
    super.onReady();
    InternetConnectionHelper.getInstance().startInternetConnection();
    InternetConnectionHelper.getInstance().startListenNetwork();

    integrateList.add(mineUserInfo);
    initLastCheckFriendId();

    AddFriendDialog.show(
        onAddClick: () async {
          await onAddFriendClick();
          checkLocationPermissionCallback();
        },
        onNotAddDismiss: checkLocationPermissionCallback);

    loginSubscription = accountRepository.isLogin.listen((isLogin) {
      if (isLogin == false) {
        _selectedFriend.value = mineUserInfo;
      }
    });
    //刷新好友列表
    _updateFriendList(_friendsList);
    friendsListSubscription =
        _friendsList.listen((list) => _updateFriendList(list));

    //刷新我的marker
    updateMineInfo(accountRepository.mineUserInfo.value);
    mineUserInfoSubscription =
        accountRepository.mineUserInfo.listen((mineInfo) {
      updateMineInfo(mineInfo);
    });
    //刷新我的定位
    final location = accountRepository.mineUserInfo.value.lastLocation.value;
    if (location != null) {
      _updateMineLocation(location);
    }
    mineLocationSubscription =
        accountRepository.mineUserInfo.value.lastLocation.listen((location) {
      _updateMineLocation(location);
    });
    //根据会员状态刷新好友列表
    memberStatusInfoSubscription =
        accountRepository.memberStatusInfo.listen((memberStatus) {
      if (memberStatus != null) {
        _updateFriendList(_friendsList);
      }
    });

    ///刷新检查有没有广告
    _refreshTrackDailyDialogs();
  }

  void _updateMineLocation(LocationInfo? location) {
    final mineInfo = accountRepository.mineUserInfo.value;
    mapController.updateOrAddMarker(Location2MarkerUtil.userInfo2Marker(
        mineInfo, selectedFriend?.id == mineInfo.id, null));
    if (isFirstShowMineLocation && location != null) {
      isFirstShowMineLocation = false;
      animateCameraToUser(mineInfo);
    }
  }

  void _updateFriendList(List<UserInfo> list) {
    integrateList.clear();
    integrateList.add(mineUserInfo);
    integrateList.addAll(list);
    mapController.replaceAllMarkers(Location2MarkerUtil.userInfoList2MarkerList(
        integrateList, accountRepository.memberIsExpired(), selectedFriend));
    if (selectedFriend != null) {
      UserInfo? userInfo = integrateList
          .firstWhereOrNull((element) => element.id == selectedFriend?.id);
      _setSelectUserInfo(userInfo ?? mineUserInfo);
    }
    _autoSelectFriend();
  }

  ///刷新检查有没有广告
  void _refreshTrackDailyDialogs() {
    trackRepository.locationTrackDailyDialogs().then((trackResponse) {
      if (trackResponse.show ?? false) {
        TrackDailyReportDialog.show(
            trackDailyList: trackResponse.trackDailyList,
            confirmOnTap: () {
              TrackChooseFriendDialog.show(
                  trackDailyList: trackResponse.trackDailyList,
                  onSelectItem: (selectInfo) {
                    onViewTraceClick(selectInfo);
                  });
            });
      }
    }).catchError((error) {
      ErrorHandler.toastError(error);
    });
  }

  void updateMineInfo(UserInfo mineInfo) {
    if (mineInfo == selectedFriend) {
      _selectedFriend.refresh();
    }
    if (mineInfo.lastLocation.value == null) {
      return;
    }
    mapController.updateOrAddMarker(Location2MarkerUtil.userInfo2Marker(
        mineInfo, selectedFriend?.id == mineInfo.id, null));
  }

  Future<void> onAddFriendClick() {
    return AddFriendPage.show();
  }

  void onMineClick() {
    MinePage.start();
  }

  void checkLocationPermissionCallback() async {
    bool isGranted = await PermissionUtil.checkLocationPermission();
    if (!isGranted) {
      CheckLocationPermissionDialog.show(
          onRequestPermissionClick: _requestLocationPermission);
    }
  }

  void onSelectUserClick(UserInfo userInfo) {
    KVUtil.putString(Constants.keyLastSelectFriendId, userInfo.id);
    if (userInfo == _selectedFriend.value) {
      return;
    }
    _setSelectUserInfo(userInfo);
  }

  void _setSelectUserInfo(UserInfo userInfo) {
    UserInfo? oldInfo = _selectedFriend.value;
    _selectedFriend.value = userInfo;
    //定时查询手机电量
    _scheduleQueryBattery();
    //修改地图选中
    int? electric = electricMap[userInfo.id];
    _updateMapSelected(oldInfo, userInfo, electric: electric);
    onFriendVisibleFraction(lastVisibleFraction ?? 0.0);
    if (!accountRepository.memberIsExpired() || userInfo.isMine == true) {
      //移动到选中的位置
      animateCameraToUser(userInfo);
    }
  }

  void _scheduleQueryBattery() {
    electricTimer?.cancel();
    final friend = _selectedFriend.value;
    if (friend == null || friend.id == Constants.mineLocationId) {
      return;
    }
    queryFriendElectric(friend);
    electricTimer = Timer.periodic(const Duration(minutes: 3), (timer) {
      queryFriendElectric(friend);
    });
  }

  void queryFriendElectric(UserInfo friend) async {
    friendsRepository
        .userElectricQuery(friend.id)
        .then((response) => response.electric)
        .then((electric) {
      //更新选中点位的电量
      if (electric == null) {
        return;
      }
      electricMap[friend.id] = electric;
      final selectFriend = _selectedFriend.value;
      if (selectFriend == null || friend.id != selectFriend.id) {
        return;
      }
      _updateMapSelected(null, selectFriend, electric: electric);
    });
  }

  void _updateMapSelected(UserInfo? oldInfo, UserInfo newInfo,
      {int? electric}) {
    List<UserInfo> markers = [];
    if (oldInfo != null && oldInfo.id != newInfo.id) {
      markers.add(oldInfo);
    }
    markers.add(newInfo);
    mapController.updateOrAddMarkers(
        Location2MarkerUtil.userInfoList2MarkerList(
            markers, accountRepository.memberIsExpired(), selectedFriend,
            electric: electric));
  }

  void animateCameraToUser(UserInfo userInfo) {
    LocationInfo? locationInfo = userInfo.lastLocation.value;
    if (locationInfo == null ||
        locationInfo.longitude == null ||
        locationInfo.latitude == null ||
        locationInfo.longitude == 0 ||
        locationInfo.latitude == 0 ||
        userInfo.blockedMe == true) {
      return;
    }
    animateCamera(
        latitude: locationInfo.latitude, longitude: locationInfo.longitude);
  }

  void animateCamera({required double? latitude, required double? longitude}) {
    mapController.animateCamera(
        CameraPosition(longitude: longitude, latitude: latitude, zoom: 18));
  }

  void onMarkerTap(Marker marker) {
    String id = marker.id;
    UserInfo? userInfo =
        integrateList.firstWhereOrNull((element) => element.id == id);
    if (userInfo == null) {
      return;
    }
    onSelectUserClick(userInfo);
  }

  void onCurrentLocationClick() async {
    //权限检查
    bool isGranted = await PermissionUtil.checkLocationPermission();
    if (!isGranted) {
      LocationPermissionDialog.show(onNextStep: _requestLocationPermission);
    } else {
      _updateCurrentLocation();
    }
  }

  void onRefreshFriendLocationClick() {
    final now = DateTime.now();
    final secondsSinceLastRefresh = now.difference(_lastRefreshTime).inSeconds;

    if (secondsSinceLastRefresh < 10) {
      final remainingSeconds = 10 - secondsSinceLastRefresh;
      ToastUtil.show('请等待 $remainingSeconds 秒后重试');
      return;
    }

    _lastRefreshTime = now;

    friendsRepository.refreshFriends().then((_) {
      ToastUtil.show(StringName.refreshFriendDataSuccess);
    }).catchError((error) {
      ErrorHandler.toastError(error);
      _lastRefreshTime = DateTime.fromMillisecondsSinceEpoch(0);
    });
  }

  void _requestLocationPermission() async {
    bool isGranted = await PermissionUtil.requestLocationPermission();
    if (isGranted) {
      _showLocationAlways();
      _updateCurrentLocation();
    } else {
      permissionRefuseDialog(settingClick: () {
        openAppSettings();
      });
      ToastUtil.show(StringName.permissionRequestFail);
    }
  }

  void _showLocationAlways() async {
    bool isGranted = await PermissionUtil.checkShowLocationAlways();
    if (!isGranted) {
      LocationAlwaysPermissionDialog.show(onNextStep: () async {
        isGranted = await PermissionUtil.requestShowLocationAlways();
        if (isGranted) {
          _updateCurrentLocation();
        }
      });
    }
  }

  void _updateCurrentLocation() {
    var lastLocation = MapHelper.getLastLocation();
    if (lastLocation == null) {
      locationListener(MapLocation location) {
        MapHelper.removeLocationListener(locationListener);
        animateCamera(
            latitude: location.latitude, longitude: location.longitude);
      }

      MapHelper.addLocationListener(locationListener);
    } else {
      animateCamera(
          latitude: lastLocation.latitude, longitude: lastLocation.longitude);
    }
  }

  onFriendClick() {
    FriendPage.start();
  }

  void onViewTraceClick(UserInfo userInfo) {
    if (!accountRepository.isLogin.value) {
      showTraceTipsDialog(onConfirm: () {
        LoginPage.start();
      });
      return;
    }
    if (!(userInfo.virtual ?? false) && accountRepository.memberIsExpired()) {
      MemberPage.start();
      return;
    }

    if (userInfo.blockedMe == true) {
      showBlockMeTipDialog(confirmOnTap: () {
        WechatShareUtil.shareWebPage().catchError((error) {
          ToastUtil.show(error.toString());
        });
      });
      return;
    }
    TrackPage.start(userInfo);
  }

  void onNewsClick() {
    if (!accountRepository.isLogin.value) {
      LoginPage.start();
      return;
    }
    NewsPage.start();
  }

  onUrgentContactClick() async {
    if (!accountRepository.isLogin.value) {
      bool isLogin = await LoginPage.start();
      if (!isLogin) {
        return;
      }
    }
    //如果没有紧急联系人，则先进入页面
    if (urgentContactRepository.contactList.isEmpty) {
      UrgentContactPage.start(isShowRequest: "1");
      return;
    }
    if (accountRepository.memberIsExpired()) {
      MemberPage.start();
      return;
    }
    final defaultContact = urgentContactRepository.getDefaultContact();
    if (defaultContact != null) {
      if (_lastRequestFavor != null &&
          DateTime.now().difference(_lastRequestFavor!).inSeconds < 30) {
        ToastUtil.show(StringName.urgentContactHelpSendTooFast);
        return;
      }
      sendUrgentContactDialog(defaultContact.phone, confirmOnTap: () {
        urgentContactRepository.contactMayDayFavor().then((value) {
          ToastUtil.show(StringName.urgentContactHelpSendSuccess);
          _lastRequestFavor = DateTime.now();
        }).catchError((error) {
          ErrorHandler.toastError(error);
        });
      });
      return;
    } else {
      ToastUtil.show(StringName.contactNoDefault);
      UrgentContactPage.start(isShowRequest: "1");
    }
  }

  void onAppBack() {
    if ((_lastPressedAt == null ||
        DateTime.now().difference(_lastPressedAt!) >
            const Duration(seconds: 2))) {
      _lastPressedAt = DateTime.now();
      ToastUtil.show(StringName.exitAppTip);
    } else {
      back();
    }
  }

  void back() {
    if (Platform.isAndroid) {
      FlutterToolAndroid.backHome();
    } else {
      SystemNavigator.pop();
    }
  }

  void initLastCheckFriendId() {
    lastCheckFriendId = KVUtil.getString(Constants.keyLastSelectFriendId, null);
    _autoSelectFriend();
  }

  void _autoSelectFriend() {
    if (isExecuteAutoSelect) {
      return;
    }
    if (lastCheckFriendId == null) {
      _setSelectUserInfo(mineUserInfo);
      isExecuteAutoSelect = true;
      return;
    }
    for (var value in integrateList) {
      if (value.id == lastCheckFriendId) {
        isExecuteAutoSelect = true;
        _setSelectUserInfo(value);
        return;
      }
    }
  }

  void onFriendVisibleFraction(double visibleFraction) {
    lastVisibleFraction = visibleFraction;
    if (visibleFraction > 0.2) {
      _requestSelectedFriendTrack();
    }
  }

  void _requestSelectedFriendTrack() {
    //查看当前选中的好友是否有记录数据
    final selectedFriend = _selectedFriend.value;
    if (selectedFriend == null || accountRepository.memberIsExpired()) {
      return;
    }
    todayTrackHelper.requestTodayTrackReport(selectedFriend.id);
  }

  void onTodayTraceClick() {
    final selectedUserInfo = _selectedFriend.value;
    if (selectedUserInfo == null) {
      return;
    }
    onViewTraceClick(selectedUserInfo);
  }

  void onTrackNoMemberClick() {
    MemberPage.start();
  }

  @override
  void onClose() {
    mineLocationSubscription?.cancel();
    friendsListSubscription?.cancel();
    loginSubscription?.cancel();
    memberStatusInfoSubscription?.cancel();
    mineUserInfoSubscription?.cancel();
  }
}
