import 'package:diameter/main.dart';
import 'package:diameter/models/log_bolus.dart';
import 'package:diameter/models/settings.dart';
import 'package:diameter/utils/date_time_utils.dart';
import 'package:objectbox/objectbox.dart';
import 'package:diameter/objectbox.g.dart' show LogEntry_;

@Entity(uid: 752131069307970560)
@Sync()
class LogEntry {
  static final Box<LogEntry> box = objectBox.store.box<LogEntry>();

  // properties
  int id;
  bool deleted;
  @Property(type: PropertyType.date)
  DateTime time;
  int? mgPerDl;
  double? mmolPerL;
  double? glucoseTrend;
  String? notes;

  // constructor
  LogEntry({
    this.id = 0,
    this.deleted = false,
    required this.time,
    this.mgPerDl,
    this.mmolPerL,
    this.glucoseTrend,
    this.notes,
  });

  // methods
  static LogEntry? get(int id) => id == 0 ? null : box.get(id);
  static List<LogEntry> getAll() => box.getAll();
  static void put(LogEntry logEntry) => box.put(logEntry);

  static void remove(int id) {
    final item = box.get(id);
    if (item != null) {
      item.deleted = true;
      box.put(item);
    }
  }

  static bool hasUncorrectedGlucose(int id) {
    final entry = box.get(id);
    if (((entry?.mgPerDl ?? 0) > Settings.targetMgPerDl ||
        (entry?.mmolPerL ?? 0) > Settings.targetMmolPerL)) {
      return !LogBolus.glucoseBolusForEntryExists(id);
    }
    return false;
  }

  static Map<DateTime, List<LogEntry>> getDailyEntryMap() {
    Map<DateTime, List<LogEntry>> dateMap = <DateTime, List<LogEntry>>{};

    QueryBuilder<LogEntry> allByDate = box
        .query(LogEntry_.deleted.equals(false))
      ..order(LogEntry_.time, flags: Order.descending);
    List<LogEntry> entries = allByDate.build().find();
    DateTime? date;

    for (LogEntry entry in entries) {
      date = DateTime.utc(entry.time.year, entry.time.month, entry.time.day);
      dateMap.putIfAbsent(date, () => <LogEntry>[]).add(entry);
    }

    return dateMap;
  }

  static List<LogEntry> getAllForDate(DateTime date) {
    DateTime startOfDay = DateTime(date.year, date.month, date.day);
    DateTime endOfDay = startOfDay.add(const Duration(days: 1));
    QueryBuilder<LogEntry> builder = box.query(LogEntry_.deleted.equals(false))
      ..order(LogEntry_.time, flags: Order.descending);
    return builder.build().find().where((entry) {
      return (entry.time.compareTo(startOfDay) >= 0 && entry.time.isBefore(endOfDay));
    }).toList();
  }

  @override
  String toString() {
    return DateTimeUtils.displayDateTime(time);
  }
}
