import {
    EntityManager,
    EntitySchema,
    ObjectLiteral,
    Repository,
} from 'typeorm'
import { databaseConnection } from '../../database/database-connection'

/**
 * If given an {@link EntityManager}, returns a {@link Repository} for the current transaction.
 * Otherwise, returns the {@link Repository} for the default connection.
 */
type RepoGetter<T extends ObjectLiteral = ObjectLiteral> = (
    entityManager?: EntityManager
) => Repository<T>

const instances = new Map<EntitySchema, RepoGetter>()

/**
 * Creates a {@link RepoGetter} for the given entity.
 * @param entity The entity to create a {@link RepoGetter} for.
 * @returns A {@link RepoGetter} for the given entity.
 */
export const repoFactory = <T extends ObjectLiteral>(
    entity: EntitySchema<T>,
): RepoGetter<T> => {
    if (instances.has(entity)) {
        return instances.get(entity) as RepoGetter<T>
    }

    const newInstance: RepoGetter<T> = (entityManager?: EntityManager) => {
        return (
            entityManager?.getRepository(entity) ??
      databaseConnection().getRepository(entity)
        )
    }

    instances.set(entity, newInstance as RepoGetter)
    return newInstance
}
