import { FindManyOptions, FindOneOptions, ObjectLiteral, Repository, SelectQueryBuilder } from "typeorm";

// Subconjunto de SelectQueryBuilder que deja fuera update()/delete()/insert()
// a nivel de tipo. No es una garantia en runtime (un `as any` la evade), pero
// junto con insert:false/update:false en cada columna de la entidad y con
// ReadonlyRepositoryGuard.spec.ts (que falla si aparece un .save/.update/
// .delete/.insert/.remove/.upsert sobre este repositorio en el codigo fuente)
// forma la doble red pedida.
export type ReadonlySelectQueryBuilder<T extends ObjectLiteral> = Pick<
  SelectQueryBuilder<T>,
  | "where"
  | "andWhere"
  | "orWhere"
  | "orderBy"
  | "addOrderBy"
  | "take"
  | "skip"
  | "limit"
  | "offset"
  | "getMany"
  | "getOne"
  | "getCount"
  | "getManyAndCount"
  | "select"
  | "leftJoin"
  | "leftJoinAndSelect"
>;

// Envoltorio de solo lectura para una tabla externa del ERP. No expone
// save/insert/update/delete/remove/upsert — ni por accidente, ni por un
// desarrollador nuevo que no conoce la regla "maeplu es solo lectura".
export class ReadonlyRepository<T extends ObjectLiteral> {
  constructor(private readonly repository: Repository<T>) {}

  find(options?: FindManyOptions<T>): Promise<T[]> {
    return this.repository.find(options);
  }

  findOne(options: FindOneOptions<T>): Promise<T | null> {
    return this.repository.findOne(options);
  }

  count(options?: FindManyOptions<T>): Promise<number> {
    return this.repository.count(options);
  }

  query<R = unknown>(sql: string, parameters?: unknown[]): Promise<R> {
    const normalized = sql.trim().toUpperCase();
    if (!normalized.startsWith("SELECT") && !normalized.startsWith("SHOW")) {
      throw new Error(
        "ReadonlyRepository.query solo permite SELECT/SHOW — se intento ejecutar: " +
          sql.slice(0, 80),
      );
    }
    return this.repository.query(sql, parameters);
  }

  createSelectQueryBuilder(alias: string): ReadonlySelectQueryBuilder<T> {
    return this.repository.createQueryBuilder(alias);
  }
}
