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

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

/// Private implementation type for `_UnitOfWorkNoticeAcknowledgementRepository` 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 _UnitOfWorkNoticeAcknowledgementRepository
    implements NoticeAcknowledgementRepository {
  /// Creates a `_UnitOfWorkNoticeAcknowledgementRepository` 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.
  _UnitOfWorkNoticeAcknowledgementRepository({
    required Map<String, NoticeAcknowledgementRecord> recordsByScopedId,
    required Map<String, int> revisionsByScopedId,
  })  : _recordsByScopedId = recordsByScopedId,
        _revisionsByScopedId = revisionsByScopedId;

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

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

  /// 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<NoticeAcknowledgementRecord?> findById({
    required String ownerId,
    required String noticeId,
  }) async {
    return _recordsByScopedId[
        _noticeAcknowledgementKey(ownerId: ownerId, noticeId: noticeId)];
  }

  /// Runs the `findByOwnerId` 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<NoticeAcknowledgementRecord>> findByOwnerId(
    String ownerId,
  ) async {
    return List<NoticeAcknowledgementRecord>.unmodifiable(
      _recordsByScopedId.values.where((record) => record.ownerId == ownerId),
    );
  }

  /// 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<NoticeAcknowledgementRecord>> findByOwner({
    required String ownerId,
    RepositoryPageRequest page = const RepositoryPageRequest(),
  }) async {
    final records = _recordsByScopedId.values
        .where((record) => record.ownerId == ownerId)
        .toList(growable: false)
      ..sort(_compareNoticeAcknowledgements);
    return _page(records, 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(NoticeAcknowledgementRecord record) async {
    final key = _noticeAcknowledgementKey(
      ownerId: record.ownerId,
      noticeId: record.noticeId,
    );
    _recordsByScopedId[key] = record;
    _revisionsByScopedId[key] = (_revisionsByScopedId[key] ?? 1) + 1;
  }

  /// Runs the `insert` 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> insert(
    NoticeAcknowledgementRecord record,
  ) async {
    final key = _noticeAcknowledgementKey(
      ownerId: record.ownerId,
      noticeId: record.noticeId,
    );
    if (_recordsByScopedId.containsKey(key)) {
      return RepositoryMutationResult.failure(
        RepositoryFailure(
          code: RepositoryFailureCode.duplicateId,
          entityId: record.noticeId,
        ),
      );
    }
    _recordsByScopedId[key] = record;
    _revisionsByScopedId[key] = 1;
    return RepositoryMutationResult.success(revision: 1);
  }
}
