import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Issuer, IssuerStatus } from '../../domain/entities/issuer.entity';
import { IIssuerRepository } from '../../domain/repositories/issuer.repository.interface';

@Injectable()
export class IssuerRepository implements IIssuerRepository {
  constructor(
    @InjectRepository(Issuer)
    private readonly repo: Repository<Issuer>,
  ) {}

  async findById(id: string): Promise<Issuer | null> {
    return this.repo.findOne({ where: { id } });
  }

  async findByUserId(userId: string): Promise<Issuer | null> {
    return this.repo.findOne({ where: { userId } });
  }

  async create(data: Partial<Issuer>): Promise<Issuer> {
    const entity = this.repo.create(data);
    return this.repo.save(entity);
  }

  async save(issuer: Issuer): Promise<Issuer> {
    return this.repo.save(issuer);
  }

  async updateStatus(id: string, status: IssuerStatus): Promise<void> {
    await this.repo.update(id, { status });
  }

  async findAndCount(options: {
    status?: string;
    search?: string;
    page: number;
    limit: number;
  }): Promise<[Issuer[], number]> {
    const { status, search, page, limit } = options;
    const qb = this.repo.createQueryBuilder('i');

    if (status) {
      qb.andWhere('i.status = :status', { status });
    }

    if (search) {
      qb.andWhere(
        '(i.company_name ILIKE :search OR i.contact_name ILIKE :search OR i.contact_email ILIKE :search)',
        { search: `%${search}%` },
      );
    }

    qb.orderBy('i.created_at', 'DESC')
      .skip((page - 1) * limit)
      .take(limit);

    return qb.getManyAndCount();
  }

  async findPending(take: number): Promise<Issuer[]> {
    return this.repo.find({
      where: { status: IssuerStatus.PENDING },
      order: { createdAt: 'ASC' },
      take,
    });
  }

  async findByIds(ids: string[]): Promise<Issuer[]> {
    if (ids.length === 0) return [];
    return this.repo
      .createQueryBuilder('i')
      .where('i.id IN (:...ids)', { ids })
      .getMany();
  }

  async count(where?: Partial<Record<string, any>>): Promise<number> {
    return this.repo.count({ where: where as any });
  }
}
