import 'dart:async';
import 'dart:io';

import 'package:geolocation/models/position.dart';
import 'package:get/get.dart';
import 'package:o2oa_all_platform/common/extension/index.dart';

import '../api/index.dart';
import '../models/index.dart';
import '../utils/index.dart';
import '../widgets/index.dart';
import 'shared_preference_service.dart';

/// 极速打卡功能
class FastCheckInService {
  // 单例
  static final FastCheckInService instance = FastCheckInService._internal();
  factory FastCheckInService() => instance;
  FastCheckInService._internal();

  // 定时器
  Timer? _timer;
  /// geolocator 定位
  GeolocatorHelper? _geoHelper;
  /// 当前定位信息
  GeoPosition? _myPosition;

  // 上班是否开启极速打卡
  bool _onDutyFastCheckInEnable = false;
  // 下班是否开启极速打卡
  bool _offDutyFastCheckInEnable = false;
  // 是否正在运行中
  bool _isRunning = false;
  // 运行时间 超过 2 分钟就结束
  int _runningTime = 0;
  // 工作地点
  final List<WorkPlaceList> _workplaceList = [];
  WorkPlaceList? _nearLeastWorkplace; // 最近的打卡地点
  bool _isInCheckInPositionRange = false; // 最近的打卡地点是否在打卡范围内
  AttendanceV2Record? _currentCheckItem; // 当前打卡对象
  bool _isPosting = false;

  /// 开始运行极速打卡
  void start() async {
    if (!Platform.isAndroid && !Platform.isIOS) return;
    if (_isRunning) return;
    OLogger.i('开始极速打卡！');
    _isRunning = true;
    final config = await AttendanceAssembleControlService.to.config();
    if (config != null &&
        (config.onDutyFastCheckInEnable == true ||
            config.offDutyFastCheckInEnable == true)) {
      _onDutyFastCheckInEnable = config.onDutyFastCheckInEnable ?? false;
      _offDutyFastCheckInEnable = config.offDutyFastCheckInEnable ?? false;
      _startTimer();
      _loadPreCheckInData();
    } else {
      OLogger.d('没有配置极速打卡!');
      _isRunning = false;
    }
  }

  /// 结束运行极速打卡
  void stop() {
    OLogger.i('结束极速打卡！');
    _timer?.cancel();
    _timer = null;
    _geoHelper?.stopLocation();
    _geoHelper = null;
    _myPosition = null;
    _nearLeastWorkplace = null;
    _currentCheckItem = null;
    _runningTime = 0;
    _isRunning = false;
  }

  /// 开始定位
  void _startLocation() async {
    // 初始化定位程序
    _geoHelper = GeolocatorHelper(callback: (position){
      _myPosition = position;
      _calNearestWorkplace();
    });
    _geoHelper?.startLocation();
  }

  /// 开始计时 2 分钟 没有运行结束就 stop
  void _startTimer() {
    /// 间隔5秒
    _timer = Timer.periodic(const Duration(milliseconds: 5000), (timer) {
      _runningTime += 5000;
      if (_runningTime >= 2 * 60 * 1000) {
        stop();
      }
    });
  }

  /// 获取打卡初始化数据
  /// 先判断数据业务 除了 固定班制 排班制 其他不进行自动打卡
  void _loadPreCheckInData() async {
    final data = await AttendanceAssembleControlService.to.loadPreCheckInData();
    if (data == null) {
      stop();
      return;
    }
    bool needCheck = data.canCheckIn ?? false; //今天是否还需要打卡
    if (needCheck) {
      // 打卡记录
      final checkItemList = data.checkItemList ?? [];
      // 是否最后一条已经打卡过的数据
      _currentCheckItem = checkItemList
          .firstWhereOrNull((element) => element.checkInResult == 'PreCheckIn');
       // 固定班制 排班制 并且有班次 id 才能进行极速打卡
      if (_currentCheckItem != null  &&
          _currentCheckItem?.shiftId?.isNotEmpty == true &&
          (_currentCheckItem?.groupCheckType == "1" ||
              _currentCheckItem?.groupCheckType == "3")) {
        needCheck = true;
      } else {
        needCheck = false;
      }
    }
    // 如果不能打卡了 就结束
    if (!needCheck) {
      OLogger.i("今天无需打卡， 全部停止。");
      stop();
    } else {
      // 开始启动定位
      _startLocation();
      // 开始查询工作场所数据
      if (data.workPlaceList != null && data.workPlaceList!.isNotEmpty) {
        _workplaceList
          ..clear()
          ..addAll(data.workPlaceList!);
        // 计算最近的打卡地点
        _calNearestWorkplace();
      }

      _tryCheckIn();
    }
  }

  /// 尝试极速打卡
  void _tryCheckIn() {
    if (_myPosition == null || _workplaceList.isEmpty) {
      OLogger.e('可能还未定位到。。。。');
      return;
    }
    if (_nearLeastWorkplace != null &&
        _currentCheckItem != null &&
        _isInCheckInPositionRange) {
      // 上班打卡
      if ((_currentCheckItem?.checkInType == 'OnDuty' &&
              _onDutyFastCheckInEnable) ||
          (_currentCheckItem?.checkInType == 'OffDuty' &&
              _offDutyFastCheckInEnable)) {
        // 是否在打卡限制时间内
        final dutyTime = _currentCheckItem?.preDutyTime ?? '';
        final preBeforeTime = _currentCheckItem?.preDutyTimeBeforeLimit ?? '';
        final preAfterTime = _currentCheckItem?.preDutyTimeAfterLimit ?? '';
        if (!_checkLimitTime(_currentCheckItem?.checkInType ?? '', dutyTime,
            preBeforeTime, preAfterTime)) {
          OLogger.e("不在限制时间内！！！！");
          return;
        }
        _postCheckIn(_currentCheckItem!, _nearLeastWorkplace!.id!);
      } else {
        OLogger.i("当前打卡类型：${_currentCheckItem?.checkInType} 不允许极速打卡！");
        stop();
      }
    }
  }

  // 打卡
  void _postCheckIn(AttendanceV2Record record, String workPlaceId) async {
    if (_isPosting) return;
    _isPosting = true;
    var post = CheckPost(
        recordId: record.id,
        checkInType: record.checkInType,
        workPlaceId: workPlaceId,
        fieldWork: false,
        signDescription: '',
        latitude: '${_myPosition!.latitude}',
        longitude: '${_myPosition!.longitude}',
        recordAddress: '${_myPosition!.address}',
        sourceType: 'FAST_CHECK');
    var deviceType = SharedPreferenceService.to
        .getString(SharedPreferenceService.currentDeviceTypeKey);
    post.sourceDevice = deviceType;

    final iddata =
        await AttendanceAssembleControlService.to.checkInPostV2(post);
    if (iddata != null) {
      OLogger.i('极速打卡成功！');
      // 发送通知
      O2OverlayEntryDialog.instance.openFastCheckInDialog(
          'attendance_fast_checkin_notify_title'.tr,
          'attendance_fast_checkin_notify_content'
              .trArgs([(iddata.recordDate ?? '')]));
      stop();
    }
    _isPosting = false;
  }

  /// 是否有打卡时间限制
  bool _checkLimitTime(String checkInType, String dutyTime,
      String preDutyTimeBeforeLimit, String preDutyTimeAfterLimit) {
    final now = DateTime.now();
    final today = now.ymd();
    final dutyTimeDate = DateTime.tryParse('$today $dutyTime:00');
    if (dutyTimeDate == null) {
      OLogger.e('时间解析出差，$today $dutyTime');
      return false;
    }
    // 极速打卡开始时间
    var fastCheckInBeforeLimit = dutyTimeDate;
    if (checkInType == 'OnDuty') {
      //上班前一个小时
      fastCheckInBeforeLimit = dutyTimeDate.addMinutes(-60);
    }

    // 极速打卡结束时间
    var fastCheckInAfterLimit = dutyTimeDate.addMinutes(60); // 下班后1个小时
    if (checkInType == 'OnDuty') {
      fastCheckInAfterLimit = dutyTimeDate;
    }

    if (preDutyTimeBeforeLimit.isNotEmpty) {
      final beforeTime = DateTime.tryParse("$today $preDutyTimeBeforeLimit:00");
      if (beforeTime != null && fastCheckInBeforeLimit.isBefore(beforeTime)) {
        fastCheckInBeforeLimit = beforeTime;
      }
    }
    if (preDutyTimeAfterLimit.isNotEmpty) {
      final afterTime = DateTime.tryParse("$today $preDutyTimeAfterLimit:00");
      if (afterTime != null && fastCheckInAfterLimit.isAfter(afterTime)) {
        fastCheckInAfterLimit = afterTime;
      }
    }
    OLogger.d(
        "打卡时间，$dutyTimeDate 极速打卡开始时间：$fastCheckInBeforeLimit 极速打卡结束时间： $fastCheckInAfterLimit");
    if (fastCheckInBeforeLimit.isBefore(now) &&
        fastCheckInAfterLimit.isAfter(now)) {
      return true;
    }
    return false;
  }

  /// 计算最近的打卡地点
  void _calNearestWorkplace() async {
    if (_myPosition == null) {
      OLogger.e('还没有定位成功！');
      return;
    }
    _isInCheckInPositionRange = false;
    if (_workplaceList.isNotEmpty) {
      for (final workplace in _workplaceList) {
        OLogger.d('工作地点： ${workplace.latitude}  ${workplace.longitude}');
        double startLatitude = _myPosition?.latitude ?? 0;
        double startLongitude = _myPosition?.longitude ?? 0;
        final lngLat = workplace.getLngLat();
        double endLatitude = lngLat[1];
        double endLongitude = lngLat[0];
        if (startLatitude != 0 && startLongitude != 0 && endLatitude != 0 && endLongitude != 0) {
          OLogger.d('坐标  workplace endLatitude:$endLatitude endLongitude:$endLongitude myPosition startLatitude: $startLatitude startLongitude: $startLongitude');
          final distance = _geoHelper?.distanceInMeters(startLatitude, startLongitude, endLatitude, endLongitude) ?? 0;
          int range = workplace.errorRange ?? 100; // 默认 100 米
          OLogger.d('距离计算：$distance $range');
          if (distance != 0 &&  distance <= range) {
            // 找到了范围内的打卡地点
            _nearLeastWorkplace = workplace;
            _isInCheckInPositionRange = true;
            _tryCheckIn();
            break;
          }
        } else {
          OLogger.e(' 错误的坐标  workplace endLatitude:$endLatitude endLongitude:$endLongitude myPosition startLatitude: $startLatitude startLongitude: $startLongitude');
        }
      }
      OLogger.d('找到最近的打卡点? ${_nearLeastWorkplace?.placeName ?? '无'}');
    }
  }
}
