import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, MoreThan } from 'typeorm';
import { BaseTenantRepository, TenantContextService } from '@iconsulting/shared';
import { IVerificationCodeRepository } from '../../../domain/repositories/verification-code.repository.interface';
import { VerificationCodeEntity } from '../../../domain/entities/verification-code.entity';
import { VerificationCodeORM } from '../../../infrastructure/database/postgres/entities/verification-code.orm';

@Injectable()
export class VerificationCodePostgresRepository
  extends BaseTenantRepository<VerificationCodeEntity, VerificationCodeORM>
  implements IVerificationCodeRepository
{
  constructor(
    @InjectRepository(VerificationCodeORM) repo: Repository<VerificationCodeORM>,
    tenantContext: TenantContextService,
  ) {
    super(repo, tenantContext);
  }

  async save(code: VerificationCodeEntity): Promise<VerificationCodeEntity> {
    const orm = this.toORM(code);
    orm.tenantId = this.getTenantId();
    const saved = await this.repo.save(orm);
    return this.toEntity(saved);
  }

  async findValidCode(phone: string, code: string): Promise<VerificationCodeEntity | null> {
    const orm = await this.createTenantQueryBuilder('vc')
      .andWhere('vc.phone = :phone', { phone })
      .andWhere('vc.code = :code', { code })
      .andWhere('vc.is_used = :isUsed', { isUsed: false })
      .andWhere('vc.expires_at > :now', { now: new Date() })
      .orderBy('vc.created_at', 'DESC')
      .getOne();
    return orm ? this.toEntity(orm) : null;
  }

  async countRecentByPhone(phone: string, hoursBack: number): Promise<number> {
    const since = new Date(Date.now() - hoursBack * 60 * 60 * 1000);
    return this.createTenantQueryBuilder('vc')
      .andWhere('vc.phone = :phone', { phone })
      .andWhere('vc.created_at > :since', { since })
      .getCount();
  }

  async markAsUsed(id: string): Promise<void> {
    await this.updateWithTenant(id, { isUsed: true } as any);
  }

  private toORM(entity: VerificationCodeEntity): VerificationCodeORM {
    const orm = new VerificationCodeORM();
    orm.id = entity.id;
    orm.tenantId = this.getTenantId();
    orm.phone = entity.phone;
    orm.code = entity.code;
    orm.expiresAt = entity.expiresAt;
    orm.isUsed = entity.isUsed;
    orm.createdAt = entity.createdAt;
    return orm;
  }

  private toEntity(orm: VerificationCodeORM): VerificationCodeEntity {
    return VerificationCodeEntity.fromPersistence({
      id: orm.id,
      phone: orm.phone,
      code: orm.code,
      expiresAt: orm.expiresAt,
      isUsed: orm.isUsed,
      createdAt: orm.createdAt,
    });
  }
}
