// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only

part of '../../models.dart';

/// Starter project defaults used when creating or scheduling tasks.
///
/// A project profile represents reusable defaults for a group of tasks. UI code
/// can let the user pick a project, then call [createTask] so new tasks inherit
/// a color, default priority, reward, difficulty, reminder profile, and duration.
///
/// The scheduler itself mostly cares about the resulting [Task] fields. Keeping
/// project defaults separate prevents every scheduling function from needing to
/// know project configuration details.
class ProjectProfile {
  /// Creates a `ProjectProfile` instance with the values required by its invariants.
  /// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
  ProjectProfile({
    required String id,
    required String name,
    required String colorKey,
    this.defaultPriority = PriorityLevel.medium,
    this.defaultReward = RewardLevel.notSet,
    this.defaultDifficulty = DifficultyLevel.notSet,
    this.defaultReminderProfile = ReminderProfile.gentle,
    int? defaultDurationMinutes,
    this.archivedAt,
  })  : id = _requiredTrimmed(
          id,
          'id',
          DomainValidationCode.blankStableId,
          'Stable id is required.',
        ),
        name = _requiredTrimmed(
          name,
          'name',
          DomainValidationCode.blankName,
          'Project name is required.',
        ),
        colorKey = _requiredTrimmed(
          colorKey,
          'colorKey',
          DomainValidationCode.blankColorKey,
          'Project color key is required.',
        ),
        defaultDurationMinutes = defaultDurationMinutes {
    _validatePositiveDuration(
      defaultDurationMinutes,
      'defaultDurationMinutes',
    );
  }

  /// Stable project id stored on tasks.
  final String id;

  /// User-facing project name.
  final String name;

  /// Theme/color token for UI rendering. This is a key, not a raw color value.
  final String colorKey;

  /// Default importance assigned when a task does not override priority.
  final PriorityLevel defaultPriority;

  /// Default motivational payoff assigned when a task does not override reward.
  final RewardLevel defaultReward;

  /// Default activation difficulty assigned when a task does not override effort.
  final DifficultyLevel defaultDifficulty;

  /// Default reminder behavior for future notification/UI layers.
  final ReminderProfile defaultReminderProfile;

  /// Optional duration estimate used for newly created tasks.
  final int? defaultDurationMinutes;

  /// When present, this project is hidden from normal pickers but tasks keep
  /// their project ids for history and filtering.
  final DateTime? archivedAt;

  /// Whether the project has been archived.
  bool get isArchived => archivedAt != null;

  /// Create a task using project defaults while allowing explicit overrides.
  ///
  /// This keeps capture and project-default behavior in one place. Callers can
  /// pass only the fields the user explicitly set; everything else falls back to
  /// this profile. The created task receives this profile's [id] as [Task.projectId].
  Task createTask({
    required String id,
    required String title,
    required DateTime createdAt,
    TaskType type = TaskType.flexible,
    TaskStatus status = TaskStatus.backlog,
    PriorityLevel? priority,
    RewardLevel? reward,
    DifficultyLevel? difficulty,
    int? durationMinutes,
    DateTime? scheduledStart,
    DateTime? scheduledEnd,
    DateTime? actualStart,
    DateTime? actualEnd,
    DateTime? completedAt,
    String? parentTaskId,
    Set<BacklogTag> backlogTags = const <BacklogTag>{},
    ReminderProfile? reminderOverride,
    DateTime? updatedAt,
  }) {
    return Task(
      id: id,
      title: title,
      projectId: this.id,
      type: type,
      status: status,
      priority: priority ?? defaultPriority,
      reward: reward ?? defaultReward,
      difficulty: difficulty ?? defaultDifficulty,
      durationMinutes: durationMinutes ?? defaultDurationMinutes,
      scheduledStart: scheduledStart,
      scheduledEnd: scheduledEnd,
      actualStart: actualStart,
      actualEnd: actualEnd,
      completedAt: completedAt,
      parentTaskId: parentTaskId,
      backlogTags: backlogTags,
      reminderOverride: reminderOverride,
      createdAt: createdAt,
      updatedAt: updatedAt ?? createdAt,
    );
  }

  /// Return a copy with selected project defaults changed.
  ProjectProfile copyWith({
    String? id,
    String? name,
    String? colorKey,
    PriorityLevel? defaultPriority,
    RewardLevel? defaultReward,
    DifficultyLevel? defaultDifficulty,
    ReminderProfile? defaultReminderProfile,
    int? defaultDurationMinutes,
    bool clearDefaultDuration = false,
    DateTime? archivedAt,
    bool clearArchivedAt = false,
  }) {
    return ProjectProfile(
      id: id ?? this.id,
      name: name ?? this.name,
      colorKey: colorKey ?? this.colorKey,
      defaultPriority: defaultPriority ?? this.defaultPriority,
      defaultReward: defaultReward ?? this.defaultReward,
      defaultDifficulty: defaultDifficulty ?? this.defaultDifficulty,
      defaultReminderProfile:
          defaultReminderProfile ?? this.defaultReminderProfile,
      defaultDurationMinutes: clearDefaultDuration
          ? null
          : (defaultDurationMinutes ?? this.defaultDurationMinutes),
      archivedAt: clearArchivedAt ? null : (archivedAt ?? this.archivedAt),
    );
  }
}
