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

part of '../../../../application_layer.dart';

/// Private implementation type for `_UnitOfWorkTaskActivityRepository` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _UnitOfWorkTaskActivityRepository implements TaskActivityRepository {
  /// Creates a `_UnitOfWorkTaskActivityRepository` 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.
  _UnitOfWorkTaskActivityRepository({
    required Map<String, TaskActivity> activitiesById,
    required Map<String, String> ownersById,
  })  : _activitiesById = activitiesById,
        _ownersById = ownersById;

  /// Private state stored as `_activitiesById` for this implementation.
  /// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
  final Map<String, TaskActivity> _activitiesById;

  /// Private state stored as `_ownersById` for this implementation.
  /// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
  final Map<String, String> _ownersById;

  /// Runs the `findById` operation and completes after its asynchronous work finishes.
  /// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
  @override
  Future<TaskActivity?> findById(String id) async => _activitiesById[id];

  /// Runs the `findByOperationId` operation and completes after its asynchronous work finishes.
  /// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
  @override
  Future<List<TaskActivity>> findByOperationId(String operationId) async {
    return List<TaskActivity>.unmodifiable(
      _activitiesById.values.where(
        (activity) => activity.operationId == operationId,
      ),
    );
  }

  /// Runs the `findByTaskId` operation and completes after its asynchronous work finishes.
  /// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
  @override
  Future<List<TaskActivity>> findByTaskId(String taskId) async {
    return List<TaskActivity>.unmodifiable(
      _activitiesById.values.where((activity) => activity.taskId == taskId),
    );
  }

  /// Runs the `findByProjectId` operation and completes after its asynchronous work finishes.
  /// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
  @override
  Future<List<TaskActivity>> findByProjectId(String projectId) async {
    return List<TaskActivity>.unmodifiable(
      _activitiesById.values.where(
        (activity) => activity.projectId == projectId,
      ),
    );
  }

  /// Runs the `findAll` operation and completes after its asynchronous work finishes.
  /// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
  @override
  Future<List<TaskActivity>> findAll() async {
    return List<TaskActivity>.unmodifiable(_activitiesById.values);
  }

  /// Runs the `findByOwner` operation and completes after its asynchronous work finishes.
  /// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
  @override
  Future<RepositoryPage<TaskActivity>> findByOwner({
    required String ownerId,
    RepositoryPageRequest page = const RepositoryPageRequest(),
  }) async {
    final activities = _activitiesById.values
        .where((activity) => _ownerFor(activity.id) == ownerId)
        .toList(growable: false)
      ..sort(_compareActivities);
    return _page(activities, page);
  }

  /// Runs the `save` operation and completes after its asynchronous work finishes.
  /// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
  @override
  Future<void> save(TaskActivity activity) async {
    _activitiesById[activity.id] = activity;
    _ownersById.putIfAbsent(activity.id, () => 'owner-1');
  }

  /// Runs the `saveAll` operation and completes after its asynchronous work finishes.
  /// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
  @override
  Future<void> saveAll(Iterable<TaskActivity> activities) async {
    for (final activity in activities) {
      _activitiesById[activity.id] = activity;
      _ownersById.putIfAbsent(activity.id, () => 'owner-1');
    }
  }

  /// Runs the `append` operation and completes after its asynchronous work finishes.
  /// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
  @override
  Future<RepositoryMutationResult> append({
    required TaskActivity activity,
    required String ownerId,
  }) async {
    if (_activitiesById.containsKey(activity.id)) {
      return RepositoryMutationResult.failure(
        RepositoryFailure(
          code: RepositoryFailureCode.duplicateId,
          entityId: activity.id,
        ),
      );
    }
    _activitiesById[activity.id] = activity;
    _ownersById[activity.id] = ownerId;
    return RepositoryMutationResult.success(revision: 1);
  }

  /// Runs the `_ownerFor` helper used inside this library.
  /// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
  String _ownerFor(String id) => _ownersById[id] ?? 'owner-1';
}
