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

part of '../sqlite_repositories.dart';

/// SQLite implementation of the app-layer operation repository.
final class _SqliteApplicationOperationRepository
    implements core.ApplicationOperationRepository {
  /// Creates an operation repository for [db].
  _SqliteApplicationOperationRepository(this.db);

  /// Shared SQLite database handle.
  final SchedulerDb db;

  /// Returns an operation by stable operation id.
  @override
  Future<core.ApplicationOperationRecord?> findById(String operationId) async {
    final row = await _operationById(operationId);
    return row == null ? null : _operationFromRow(row);
  }

  /// Returns an owner-scoped operation by operation id.
  @override
  Future<core.ApplicationOperationRecord?> findByIdempotencyKey({
    required String ownerId,
    required String operationId,
  }) async {
    final row = await _operationById(operationId);
    if (row == null || row.ownerId != ownerId) {
      return null;
    }
    return _operationFromRow(row);
  }

  /// Saves [operation], replacing an existing row with the same id.
  @override
  Future<void> save(core.ApplicationOperationRecord operation) async {
    await db.applicationOperations.insertOnConflictUpdate(
      _operationCompanion(operation),
    );
  }

  /// Inserts [operation] when absent.
  @override
  Future<core.RepositoryMutationResult> insertIfAbsent(
    core.ApplicationOperationRecord operation,
  ) async {
    if (await _operationById(operation.operationId) != null) {
      return _mutationFailure(
        core.RepositoryFailureCode.duplicateOperation,
        entityId: operation.operationId,
      );
    }
    await db
        .into(db.applicationOperations)
        .insert(_operationCompanion(operation));
    return core.RepositoryMutationResult.success(revision: 1);
  }

  /// Returns a raw operation row by operation id.
  Future<ApplicationOperationRow?> _operationById(String operationId) {
    return (db.select(db.applicationOperations)
          ..where((table) => table.operationId.equals(operationId)))
        .getSingleOrNull();
  }
}

/// Builds a Drift companion for [operation].
ApplicationOperationsCompanion _operationCompanion(
  core.ApplicationOperationRecord operation,
) {
  return ApplicationOperationsCompanion.insert(
    operationId: operation.operationId,
    ownerId: operation.ownerId,
    operationName: operation.operationName,
    committedAtUtc: operation.committedAt.toUtc(),
  );
}

/// Converts an operation row to a core record.
core.ApplicationOperationRecord _operationFromRow(ApplicationOperationRow row) {
  return core.ApplicationOperationRecord(
    operationId: row.operationId,
    ownerId: row.ownerId,
    operationName: row.operationName,
    committedAt: row.committedAtUtc.toUtc(),
  );
}
