//package space.luminic.finance.services // //import kotlinx.coroutines.reactive.awaitFirstOrNull //import kotlinx.coroutines.reactive.awaitSingle //import org.bson.types.ObjectId //import org.springframework.data.domain.Sort //import org.springframework.data.domain.Sort.Direction //import org.springframework.data.mongodb.core.ReactiveMongoTemplate //import org.springframework.data.mongodb.core.aggregation.Aggregation.addFields //import org.springframework.data.mongodb.core.aggregation.Aggregation.lookup //import org.springframework.data.mongodb.core.aggregation.Aggregation.match //import org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation //import org.springframework.data.mongodb.core.aggregation.Aggregation.sort //import org.springframework.data.mongodb.core.aggregation.Aggregation.unwind //import org.springframework.data.mongodb.core.aggregation.AggregationOperation //import org.springframework.data.mongodb.core.aggregation.ConvertOperators //import org.springframework.data.mongodb.core.query.Criteria //import org.springframework.stereotype.Service //import space.luminic.finance.dtos.TransactionDTO //import space.luminic.finance.models.NotFoundException //import space.luminic.finance.models.Transaction //import space.luminic.finance.repos.TransactionRepo // //@Service //class TransactionServiceMongoImpl( // private val mongoTemplate: ReactiveMongoTemplate, // private val transactionRepo: TransactionRepo, // private val categoryService: CategoryService, //) : TransactionService { // // // private fun basicAggregation(spaceId: String): List { // val addFieldsOI = addFields() // .addField("createdByOI") // .withValue(ConvertOperators.valueOf("createdById").convertToObjectId()) // .addField("updatedByOI") // .withValue(ConvertOperators.valueOf("updatedById").convertToObjectId()) // .addField("fromAccountIdOI") // .withValue(ConvertOperators.valueOf("fromAccountId").convertToObjectId()) // .addField("toAccountIdOI") // .withValue(ConvertOperators.valueOf("toAccountId").convertToObjectId()) // .addField("categoryIdOI") // .withValue(ConvertOperators.valueOf("categoryId").convertToObjectId()) // .build() // // val lookupFromAccount = lookup("accounts", "fromAccountIdOI", "_id", "fromAccount") // val unwindFromAccount = unwind("fromAccount") // val lookupToAccount = lookup("accounts", "toAccountIdOI", "_id", "toAccount") // val unwindToAccount = unwind("toAccount", true) // // val lookupCategory = lookup("categories", "categoryIdOI", "_id", "category") // val unwindCategory = unwind("category") // // val lookupCreatedBy = lookup("users", "createdByOI", "_id", "createdBy") // val unwindCreatedBy = unwind("createdBy") // // val lookupUpdatedBy = lookup("users", "updatedByOI", "_id", "updatedBy") // val unwindUpdatedBy = unwind("updatedBy") // val matchCriteria = mutableListOf() // matchCriteria.add(Criteria.where("spaceId").`is`(spaceId)) // val matchStage = match(Criteria().andOperator(*matchCriteria.toTypedArray())) // // return listOf( // matchStage, // addFieldsOI, // lookupFromAccount, // unwindFromAccount, // lookupToAccount, // unwindToAccount, // lookupCategory, // unwindCategory, // lookupCreatedBy, // unwindCreatedBy, // lookupUpdatedBy, // unwindUpdatedBy // ) // } // // override suspend fun getTransactions( // spaceId: String, // filter: TransactionService.TransactionsFilter, // sortBy: String, // sortDirection: String // ): List { // val allowedSortFields = setOf("date", "amount", "category.name", "createdAt") // require(sortBy in allowedSortFields) { "Invalid sort field: $sortBy" } // // val direction = when (sortDirection.uppercase()) { // "ASC" -> Direction.ASC // "DESC" -> Direction.DESC // else -> throw IllegalArgumentException("Sort direction must be 'ASC' or 'DESC'") // } // val basicAggregation = basicAggregation(spaceId) // // val sort = sort(Sort.by(direction, sortBy)) // val matchCriteria = mutableListOf() // filter.dateFrom?.let { matchCriteria.add(Criteria.where("date").gte(it)) } // filter.dateTo?.let { matchCriteria.add(Criteria.where("date").lte(it)) } // val matchStage = match(Criteria().andOperator(*matchCriteria.toTypedArray())) // val aggregation = // newAggregation( // matchStage, // *basicAggregation.toTypedArray(), // sort // ) // // return mongoTemplate.aggregate(aggregation, "transactions", Transaction::class.java) // .collectList() // .awaitSingle() // } // // override suspend fun getTransaction( // spaceId: String, // transactionId: String // ): Transaction { // val matchCriteria = mutableListOf() // matchCriteria.add(Criteria.where("spaceId").`is`(spaceId)) // matchCriteria.add(Criteria.where("_id").`is`(ObjectId(transactionId))) // val matchStage = match(Criteria().andOperator(*matchCriteria.toTypedArray())) // // val aggregation = // newAggregation( // matchStage, // ) // return mongoTemplate.aggregate(aggregation, "transactions", Transaction::class.java) // .awaitFirstOrNull() ?: throw NotFoundException("Transaction with ID $transactionId not found") // } // // override suspend fun createTransaction( // spaceId: String, // transaction: TransactionDTO.CreateTransactionDTO // ): Transaction { // if (transaction.type == Transaction.TransactionType.TRANSFER && transaction.toAccountId == null) { // throw IllegalArgumentException("Cannot create a transaction with type TRANSFER without a toAccountId") // } // val category = categoryService.getCategory(spaceId, transaction.categoryId) // if (transaction.type != Transaction.TransactionType.TRANSFER && transaction.type.name != category.type.name) { // throw IllegalArgumentException("Transaction type should match with category type") // } // val transaction = Transaction( // spaceId = spaceId, // type = transaction.type, // kind = transaction.kind, // categoryId = transaction.categoryId, // comment = transaction.comment, // amount = transaction.amount, // fees = transaction.fees, // date = transaction.date, // fromAccountId = transaction.fromAccountId, // toAccountId = transaction.toAccountId, // ) // return transactionRepo.save(transaction).awaitSingle() // } // // override suspend fun updateTransaction( // spaceId: String, // transaction: TransactionDTO.UpdateTransactionDTO // ): Transaction { // if (transaction.type == Transaction.TransactionType.TRANSFER && transaction.toAccountId == null) { // throw IllegalArgumentException("Cannot edit a transaction with type TRANSFER without a toAccountId") // } // val exitingTx = getTransaction(spaceId, transaction.id) // val transaction = exitingTx.copy( // spaceId = exitingTx.spaceId, // type = transaction.type, // kind = transaction.kind, // categoryId = transaction.category, // comment = transaction.comment, // amount = transaction.amount, // fees = transaction.fees, // date = transaction.date, // fromAccountId = transaction.fromAccountId, // toAccountId = transaction.toAccountId, // ) // return transactionRepo.save(transaction).awaitSingle() // } // // override suspend fun deleteTransaction(spaceId: String, transactionId: String) { // val transaction = getTransaction(spaceId, transactionId) // transaction.isDeleted = true // transactionRepo.save(transaction).awaitSingle() // } // // //}