import 'dart:collection';

import 'package:app_business/generated/base.pbenum.dart';
import 'package:app_business/service/api.dart';
import 'package:track_common/model/event_state.dart';
import 'package:track_common/service/map_watch.dart';
import 'package:track_common/track_common.dart';
import 'package:track_common/widget.dart';

class EventInManage {
  int id = 0;
  String name = '';
  String qrCode = '';
  var isAllowEdit = true;
  var isAllowDel = true;
  var state = EventState.idle;
  var userList = <UserInManage>[];
  var startAt = '';
  var endAt = '';
}

enum UserState { idle, hasRoute, isStart, isFinish }

class UserInManage {
  var id = 0;
  var checkId = 0;
  var name = '';
  var phone = '';
  var bandSN = '';
  var checkTime = '';
  var state = UserState.idle;
  var routeName = '';
  var isAllowDel = true;
}

class RouteInfo {
  var id = 0;
  var name = '';
}

class EventManagerController extends GetxController {
  final selectedId = Rx<int?>(null);
  final eventList = <EventInManage>[].obs;
  ApiService get _api => Get.find();
  final filterDate = DateTime.now().obs;
  final selectedUser = HashSet<int>().obs;
  RouteInfo? tmpSelectRoute;

  EventInManage? get selected {
    for (var e in eventList) {
      if (e.id == selectedId.value) {
        return e;
      }
    }
    return null;
  }

  Iterable<UserInManage> get userList => selected?.userList ?? [];

  String get dateStr =>
      '${filterDate.value.year}-${filterDate.value.month}-${filterDate.value.day}';

  MapWatch? get mapWatch => Get.find<MapWatchService>().instance;
  int? get mapId => mapWatch?.id;

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

    workFlush();
  }

  Future<void> workFlush() async {
    while (!isClosed) {
      try {
        await flushList();
      } catch (e) {
        warn('flush fail: ', e);
      }
      await 1.seconds.delay();
    }
  }

  Future<void> flushList() async {
    final mapWatch = this.mapWatch;

    if (mapWatch != null) {
      final date = filterDate.value;
      final d = DateTime(date.year, date.month, date.day);

      final r = await _api.stub.toMatchRegusterList(ToMatchRegusterListRequest()
        ..mapId = mapWatch.id
        ..startSecond = Int64(d.millisecondsSinceEpoch ~/ 1000));

      eventList.value = r.list
          .map((e) => EventInManage()
            ..id = e.id
            ..name = e.name
            ..qrCode = e.qrCode
            ..isAllowEdit = e.isAllowEdit
            ..isAllowDel = e.isAllowDel
            ..startAt = e.matchBt
            ..endAt = e.matchEt
            ..state = switch (e.state) {
              0 => EventState.idle,
              1 => EventState.start,
              _ => EventState.finish,
            }
            ..userList = e.userList
                .map((u) => UserInManage()
                  ..id = u.oId
                  ..checkId = u.mciId
                  ..name = u.nickname
                  ..phone = u.phone
                  ..routeName = u.cName
                  ..bandSN = u.hrSn
                  ..isAllowDel = u.isAllowDel
                  ..state = switch (u.cState) {
                    CState.ToUnSend => UserState.idle,
                    CState.ToUnStart => UserState.hasRoute,
                    CState.ToStart => UserState.isStart,
                    _ => UserState.isFinish,
                  }
                  ..checkTime = u.chackInsTime)
                .toList())
          .toList();
    }
  }

  Future<void> deleteEvent(EventInManage event) async {
    Get.dialog(AppDialog(
        title: const Text('删除比赛'),
        content: const Text('确认删除？'),
        onCancel: () => Get.back(),
        onConfirm: () async {
          _api.stub
              .toMatchRegusterDel(IdRequest()..id = Int64(event.id))
              .then((p0) {}, onError: (e) {
            Get.snackbar('删除失败', '$e');
          });
          Get.back();
        }));
  }

  Future<void> eventEdit(int id, EventRegisterInfo event) {
    return _api.eventEdit(id, event);
  }

  Future<Iterable<RouteInfo>> routeList(UserInManage user) async {
    final r = await _api.stub
        .toCourseSelectList(IdRequest()..id = Int64(user.checkId));
    return r.list.map((e) => RouteInfo()
      ..id = e.cId
      ..name = e.cName);
  }

  Future<void> routeAlloc(UserInManage user, RouteInfo route) async {
    debug('选择路线 ${route.name}');
    await _api.eventUserAllocRoute(user.checkId, route.id);
  }

  Future<void> userStart(UserInManage user) async {
    await _api.stub.matchChackInsStart(IdRequest()..id = Int64(user.checkId));
  }

  Future<void> routeAllocAll() async {
    final idList = selectedUser.value.toList();
    if (idList.isEmpty) {
      Get.snackbar('操作失败', '请选择1个以上的用户');
      return;
    }
    await _api.eventUserAllocRouteAll(idList);
  }

  Future<void> userStartAll() async {
    final idList = selectedUser.value.toList();
    if (idList.isEmpty) {
      Get.snackbar('操作失败', '请选择1个以上的用户');
      return;
    }
    await _api.eventUserStartAll(idList);
  }

  Future<void> userRestartAll() async {
    final idList = selectedUser.value.toList();
    if (idList.isEmpty) {
      Get.snackbar('操作失败', '请选择1个以上的用户');
      return;
    }
    await _api.eventUserRestartAll(idList);
  }

  Future<void> userDelAll() async {
    final idList = selectedUser.value.toList();
    if (idList.isEmpty) {
      Get.snackbar('操作失败', '请选择1个以上的用户');
      return;
    }
    await _api.eventUserDelAll(idList);
  }

  Future<void> deleteSignIn(UserInManage user) async {
    Get.dialog(AppDialog(
        title: const Text('删除签到'),
        content: const Text('确认删除？'),
        onCancel: () => Get.back(),
        onConfirm: () async {
          _api.stub
              .matchChackInsDel(IdRequest()..id = Int64(user.checkId))
              .then((p0) {
            debug('删除签到：${user.checkId}');
          }, onError: (e) {
            Get.snackbar('删除失败', '$e');
          });
          Get.back();
        }));
  }

  Future<void> userStopGame(UserInManage user) async {
    await _api.stub
        .matchChackInsForceFinish(IdRequest()..id = Int64(user.checkId));
  }

  Future<void> userRestartGame(UserInManage user) async {
    await _api.stub
        .matchChackInsForceResume(IdRequest()..id = Int64(user.checkId));
  }
}
