"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypeOrmTransactionRepository = void 0;
const typeorm_1 = require("typeorm");
const transaction_entity_1 = require("../entities/transaction.entity");
const data_source_1 = require("../data-source");
const transaction_mapper_1 = require("./mappers/transaction.mapper");
class TypeOrmTransactionRepository {
    get repository() {
        return data_source_1.AppDataSource.getRepository(transaction_entity_1.TransactionEntity);
    }
    async findById(id) {
        const entity = await this.repository.findOneBy({ id });
        return entity ? transaction_mapper_1.transactionMapper.toDomain(entity) : null;
    }
    async findByHash(hash) {
        const entity = await this.repository.findOneBy({ hash });
        return entity ? transaction_mapper_1.transactionMapper.toDomain(entity) : null;
    }
    async findByAddressIds(addressIds, options) {
        if (addressIds.length === 0) {
            return [];
        }
        const dataMatchClauses = addressIds
            .map((_, index) => `(
          JSON_SEARCH(transaction.data, 'one', :addressId_${index}, NULL, '$[*].to') IS NOT NULL
          OR
          JSON_SEARCH(transaction.data, 'one', :addressId_${index}, NULL, '$[*].from') IS NOT NULL
        )`)
            .join(' OR ');
        const dataMatchParams = addressIds.reduce((params, id, index) => {
            params[`addressId_${index}`] = id;
            return params;
        }, {});
        const entities = await this.repository
            .createQueryBuilder('transaction')
            .where(new typeorm_1.Brackets((qb) => {
            qb.where('transaction.fromAddressId IN (:...addressIds)', {
                addressIds,
            }).orWhere('transaction.toAddressId IN (:...addressIds)', {
                addressIds,
            });
            if (dataMatchClauses) {
                qb.orWhere(dataMatchClauses, dataMatchParams);
            }
        }))
            .orderBy('transaction.timestamp', 'DESC')
            .take(options?.limit)
            .skip(options?.offset)
            .getMany();
        return entities.map(transaction_mapper_1.transactionMapper.toDomain);
    }
    async findByFilters(filters, options) {
        const qb = this.repository.createQueryBuilder('transaction');
        if (filters.walletId) {
            qb.innerJoin('addresses', 'address', 'address.walletId = :walletId AND (address.id = transaction.fromAddressId OR address.id = transaction.toAddressId OR JSON_CONTAINS(transaction.data, JSON_QUOTE(address.id)) = 1)', { walletId: filters.walletId });
        }
        if (filters.networkId) {
            qb.andWhere('transaction.networkId = :networkId', { networkId: filters.networkId });
        }
        if (filters.tokenId) {
            qb.andWhere('transaction.interactedWith = :tokenId', { tokenId: filters.tokenId });
        }
        if (filters.status) {
            qb.andWhere('transaction.status = :status', { status: filters.status });
        }
        if (filters.method) {
            qb.andWhere('transaction.method = :method', { method: filters.method });
        }
        const entities = await qb
            .orderBy('transaction.timestamp', 'DESC')
            .take(options?.limit)
            .skip(options?.offset)
            .getMany();
        return entities.map(transaction_mapper_1.transactionMapper.toDomain);
    }
    async save(transaction) {
        const entity = await this.repository.save(transaction_mapper_1.transactionMapper.toEntity(transaction));
        return transaction_mapper_1.transactionMapper.toDomain(entity);
    }
    async update(transaction) {
        const entity = await this.repository.save(transaction_mapper_1.transactionMapper.toEntity(transaction));
        return transaction_mapper_1.transactionMapper.toDomain(entity);
    }
    async delete(id) {
        await this.repository.delete(id);
    }
}
exports.TypeOrmTransactionRepository = TypeOrmTransactionRepository;
//# sourceMappingURL=typeorm-transaction.repository.js.map