import 'package:diameter/main.dart';
import 'package:diameter/models/bolus_profile.dart';
import 'package:diameter/utils/date_time_utils.dart';
import 'package:flutter/material.dart';
import 'package:objectbox/objectbox.dart';
import 'package:diameter/objectbox.g.dart' show Bolus_, BolusProfile_;

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

  // properties
  int id;
  bool deleted;
  @Property(type: PropertyType.date)
  DateTime startTime;
  @Property(type: PropertyType.date)
  DateTime endTime;
  double units;
  double carbs;
  int? mgPerDl;
  double? mmolPerL;

  // relations
  final bolusProfile = ToOne<BolusProfile>();

  // constructor
  Bolus({
    this.id = 0,
    this.deleted = false,
    required this.startTime,
    required this.endTime,
    this.units = 0,
    this.carbs = 0,
    this.mgPerDl,
    this.mmolPerL,
  });

  // methods
  static Bolus? get(int id) => box.get(id);
  static void put(Bolus bolus) => box.put(bolus);

  static List<Bolus> getAllForProfile(int id) {
    QueryBuilder<Bolus> builder = box.query(Bolus_.deleted.equals(false))
      ..order(Bolus_.startTime);
    builder.link(Bolus_.bolusProfile, BolusProfile_.id.equals(id));
    return builder.build().find();
  }

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

  static Bolus? getRateForTime(DateTime? dateTime) {
    if (dateTime != null) {
      final bolusProfile = BolusProfile.getActive(dateTime);
      final time = DateTimeUtils.convertTimeOfDayToDateTime(
          TimeOfDay.fromDateTime(dateTime));
      if (bolusProfile != null) {
        final rates = Bolus.getAllForProfile(bolusProfile.id);
        final result = rates.where((rate) {
          DateTime endTime = rate.endTime == dummyDate
              ? rate.endTime.add(const Duration(days: 1))
              : rate.endTime;
          return (time.isAfter(rate.startTime) ||
                  time.isAtSameMomentAs(rate.startTime)) &&
              time.isBefore(endTime);
        });
        return result.length != 1 ? null : result.single;
      }
    }
    return null;
  }

  @override
  String toString() {
    return DateTimeUtils.displayTime(startTime);
  }
}
