import { DataSource, EntityTarget, ObjectLiteral, Repository } from 'typeorm';
import { TenantContextService } from '@it0/common';

export abstract class TenantAwareRepository<T extends ObjectLiteral> {
  constructor(
    protected readonly dataSource: DataSource,
    protected readonly entity: EntityTarget<T>,
  ) {}

  protected async withRepository<R>(fn: (repo: Repository<T>) => Promise<R>): Promise<R> {
    const schema = TenantContextService.getSchemaName();
    const queryRunner = this.dataSource.createQueryRunner();
    try {
      await queryRunner.query(`SET search_path TO "${schema}", public`);
      const repo = queryRunner.manager.getRepository(this.entity);
      return await fn(repo);
    } finally {
      await queryRunner.release();
    }
  }

  async findById(id: string): Promise<T | null> {
    return this.withRepository((repo) => repo.findOneBy({ id } as any));
  }

  async save(entity: T): Promise<T> {
    return this.withRepository((repo) => repo.save(entity));
  }

  async findAll(): Promise<T[]> {
    return this.withRepository((repo) => repo.find());
  }

  async remove(entity: T): Promise<T> {
    return this.withRepository((repo) => repo.remove(entity));
  }
}
