import '../../internal/application/CommitmentClass.dart';

/// The container a set of commitments belongs to — "Workout", "Thesis",
/// "Get the flat sorted". A goal owns its tasks through
/// [Commitment.parentId]; it never carries debt itself, because debt belongs
/// to the specific thing you said you would do, not the ambition behind it.
class Goal {
  String? id;

  String title;

  String description;

  String category;

  /// The default class inherited by tasks created inside this goal.
  CommitmentClass defaultClass;

  DateTime? startDate;

  /// Optional deadline for the goal as a whole.
  DateTime? targetDate;

  /// Colour accent, stored as a hex string so the goal reads consistently
  /// wherever it appears.
  String colourHex;

  bool archived;

  // ── Derived, supplied by the server ─────────────────────────────────────

  int totalTasks;

  int completedTasks;

  int overdueTasks;

  /// Debt accrued across every task under this goal.
  double debtContribution;

  Goal({
    this.id,
    this.title = "",
    this.description = "",
    this.category = "",
    this.defaultClass = CommitmentClass.Standard,
    this.startDate,
    this.targetDate,
    this.colourHex = "",
    this.archived = false,
    this.totalTasks = 0,
    this.completedTasks = 0,
    this.overdueTasks = 0,
    this.debtContribution = 0,
  });

  factory Goal.fromJson(Map<String, dynamic> json) {
    return Goal(
      id: json['id'],
      title: json['title'] ?? "",
      description: json['description'] ?? "",
      category: json['category'] ?? "",
      defaultClass: getCommitmentClass(json['defaultClass']),
      startDate: DateTime.tryParse(json['startDate'] ?? ""),
      targetDate: DateTime.tryParse(json['targetDate'] ?? ""),
      colourHex: json['colourHex'] ?? "",
      archived: json['archived'] ?? false,
      totalTasks: json['totalTasks'] ?? 0,
      completedTasks: json['completedTasks'] ?? 0,
      overdueTasks: json['overdueTasks'] ?? 0,
      debtContribution: (json['debtContribution'] ?? 0).toDouble(),
    );
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['id'] = id;
    data['title'] = title;
    data['description'] = description;
    data['category'] = category;
    data['defaultClass'] = defaultClass.name;
    data['startDate'] = startDate?.toIso8601String();
    data['targetDate'] = targetDate?.toIso8601String();
    data['colourHex'] = colourHex;
    data['archived'] = archived;
    return data;
  }

  /// 0..1 across the goal's tasks.
  double get progress {
    if (totalTasks == 0) {
      return 0;
    }
    return completedTasks / totalTasks;
  }

  /// A goal is in trouble when a meaningful share of its tasks are past their
  /// windows, not merely because one slipped.
  bool get slipping {
    if (totalTasks == 0) {
      return false;
    }
    return overdueTasks / totalTasks >= 0.34;
  }

  int get remainingTasks {
    final int remaining = totalTasks - completedTasks;
    return remaining > 0 ? remaining : 0;
  }
}
