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

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

/// Private implementation type for `_UnitOfWorkProjectStatisticsRepository` 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 _UnitOfWorkProjectStatisticsRepository
    implements ProjectStatisticsRepository {
  /// Creates a `_UnitOfWorkProjectStatisticsRepository` 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.
  _UnitOfWorkProjectStatisticsRepository({
    required Map<String, ProjectStatistics> statisticsByProjectId,
    required Map<String, String> ownersByProjectId,
    required Map<String, int> revisionsByProjectId,
  })  : _statisticsByProjectId = statisticsByProjectId,
        _ownersByProjectId = ownersByProjectId,
        _revisionsByProjectId = revisionsByProjectId;

  /// Private state stored as `_statisticsByProjectId` 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, ProjectStatistics> _statisticsByProjectId;

  /// Private state stored as `_ownersByProjectId` 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> _ownersByProjectId;

  /// Private state stored as `_revisionsByProjectId` 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, int> _revisionsByProjectId;

  /// 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<ProjectStatistics?> findByProjectId(String projectId) async {
    return _statisticsByProjectId[projectId];
  }

  /// Runs the `findRecordByProjectId` 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<RepositoryRecord<ProjectStatistics>?> findRecordByProjectId(
    String projectId,
  ) async {
    final statistics = _statisticsByProjectId[projectId];
    if (statistics == null) {
      return null;
    }
    return RepositoryRecord(
      value: statistics,
      ownerId: _ownersByProjectId[projectId] ?? 'owner-1',
      revision: _revisionsByProjectId[projectId] ?? 1,
    );
  }

  /// 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<ProjectStatistics>> findAll() async {
    return List<ProjectStatistics>.unmodifiable(_statisticsByProjectId.values);
  }

  /// 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(ProjectStatistics statistics) async {
    _statisticsByProjectId[statistics.projectId] = statistics;
    _ownersByProjectId.putIfAbsent(statistics.projectId, () => 'owner-1');
    _revisionsByProjectId[statistics.projectId] =
        (_revisionsByProjectId[statistics.projectId] ?? 1) + 1;
  }

  /// Runs the `saveIfRevision` 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> saveIfRevision({
    required ProjectStatistics statistics,
    required String ownerId,
    required int expectedRevision,
  }) async {
    final projectId = statistics.projectId;
    if (!_statisticsByProjectId.containsKey(projectId) ||
        (_ownersByProjectId[projectId] ?? 'owner-1') != ownerId) {
      return RepositoryMutationResult.failure(
        RepositoryFailure(
          code: RepositoryFailureCode.notFound,
          entityId: projectId,
        ),
      );
    }
    final actualRevision = _revisionsByProjectId[projectId] ?? 1;
    if (actualRevision != expectedRevision) {
      return RepositoryMutationResult.failure(
        RepositoryFailure(
          code: RepositoryFailureCode.staleRevision,
          entityId: projectId,
          expectedRevision: expectedRevision,
          actualRevision: actualRevision,
        ),
      );
    }
    final nextRevision = actualRevision + 1;
    _statisticsByProjectId[projectId] = statistics;
    _ownersByProjectId[projectId] = ownerId;
    _revisionsByProjectId[projectId] = nextRevision;
    return RepositoryMutationResult.success(revision: nextRevision);
  }
}
