import { Injectable } from '@nestjs/common';
import { DataSource, Repository } from 'typeorm';
import { ReferralCode } from '../../domain/entities/referral-code.entity';
import * as crypto from 'crypto';

@Injectable()
export class ReferralCodeRepository {
  private readonly repo: Repository<ReferralCode>;

  constructor(private readonly dataSource: DataSource) {
    this.repo = this.dataSource.getRepository(ReferralCode);
  }

  async findByTenantId(tenantId: string): Promise<ReferralCode | null> {
    return this.repo.findOne({ where: { tenantId } });
  }

  async findByCode(code: string): Promise<ReferralCode | null> {
    return this.repo.findOne({ where: { code } });
  }

  async create(tenantId: string, userId: string): Promise<ReferralCode> {
    const code = await this.generateUniqueCode(tenantId);
    const entity = this.repo.create({ tenantId, userId, code });
    return this.repo.save(entity);
  }

  async incrementClickCount(id: string): Promise<void> {
    await this.repo.increment({ id }, 'clickCount', 1);
  }

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

  /**
   * Generate referral code: IT0-{tenantPrefix3}-{random4}
   * e.g. IT0-ACM-X9K2
   */
  private async generateUniqueCode(tenantSlug: string): Promise<string> {
    for (let attempt = 0; attempt < 10; attempt++) {
      const prefix = tenantSlug
        .toUpperCase()
        .replace(/[^A-Z0-9]/g, '')
        .slice(0, 3)
        .padEnd(3, 'X');
      const random = crypto.randomBytes(3).toString('hex').toUpperCase().slice(0, 4);
      const code = `IT0-${prefix}-${random}`;
      const existing = await this.repo.findOne({ where: { code } });
      if (!existing) return code;
    }
    // Fallback: fully random
    return `IT0-${crypto.randomBytes(6).toString('hex').toUpperCase().slice(0, 8)}`;
  }
}
