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

part of '../../persistence_memory.dart';

/// In-memory owner settings repository with owner scoping and revision checks.
final class InMemorySettingsRepository implements SettingsRepository {
  /// Private state stored as `_records` 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, _Record<core.OwnerSettings>> _records =
      <String, _Record<core.OwnerSettings>>{};

  /// 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<RepoResult<core.OwnerSettings?>> findByOwner({
    required core.OwnerId ownerId,
  }) async {
    final record = _records[ownerId.value];
    if (record == null || record.ownerId != ownerId) {
      return const Right(null);
    }
    return Right(_cloneSettings(record));
  }

  /// 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<RepoResult<core.Revision>> insert({
    required core.OwnerId ownerId,
    required core.OwnerSettings settings,
  }) async {
    if (_records.containsKey(ownerId.value)) {
      return Left(RepositoryDuplicateId(entityId: ownerId.value));
    }
    final ownedSettings = settings.ownerId == ownerId.value
        ? settings
        : settings.copyWith(ownerId: ownerId.value);
    _records[ownerId.value] = _Record(
      id: ownerId.value,
      ownerId: ownerId,
      value: _cloneSettingsValue(
        ownedSettings,
        revision: core.Revision.initial,
        createdAt: _epoch,
        updatedAt: _epoch,
      ),
      revision: core.Revision.initial,
      createdAt: _epoch,
      updatedAt: _epoch,
    );
    return const Right(core.Revision.initial);
  }

  /// 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<RepoResult<core.Revision>> save({
    required core.OwnerId ownerId,
    required core.OwnerSettings settings,
    required core.Revision expectedRevision,
  }) async {
    final checked = _checkWrite(
      records: _records,
      id: ownerId.value,
      ownerId: ownerId,
      expectedRevision: expectedRevision,
    );
    if (checked is Left<RepositoryFailure, _Record<core.OwnerSettings>>) {
      return Left(checked.value);
    }
    final record = checked.right;
    final nextRevision = record.revision.next();
    final ownedSettings = settings.ownerId == ownerId.value
        ? settings
        : settings.copyWith(ownerId: ownerId.value);
    _records[ownerId.value] = record.copyWith(
      value: _cloneSettingsValue(
        ownedSettings,
        revision: nextRevision,
        createdAt: record.createdAt,
        updatedAt: _epoch,
      ),
      revision: nextRevision,
      updatedAt: _epoch,
    );
    return Right(nextRevision);
  }
}
