import { Injectable } from '@nestjs/common';
import { DataSource, Repository } from 'typeorm';
import { ReferralRelationship, ReferralStatus } from '../../domain/entities/referral-relationship.entity';

@Injectable()
export class ReferralRelationshipRepository {
  private readonly repo: Repository<ReferralRelationship>;

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

  async findByReferredTenantId(referredTenantId: string): Promise<ReferralRelationship | null> {
    return this.repo.findOne({ where: { referredTenantId } });
  }

  async findAllByReferrerTenantId(
    referrerTenantId: string,
    limit = 20,
    offset = 0,
  ): Promise<{ items: ReferralRelationship[]; total: number }> {
    const [items, total] = await this.repo.findAndCount({
      where: { referrerTenantId },
      order: { registeredAt: 'DESC' },
      take: limit,
      skip: offset,
    });
    return { items, total };
  }

  async findAll(
    status?: ReferralStatus,
    limit = 50,
    offset = 0,
  ): Promise<{ items: ReferralRelationship[]; total: number }> {
    const where = status ? { status } : {};
    const [items, total] = await this.repo.findAndCount({
      where,
      order: { registeredAt: 'DESC' },
      take: limit,
      skip: offset,
    });
    return { items, total };
  }

  async create(
    referrerTenantId: string,
    referredTenantId: string,
    referralCode: string,
    level = 1,
  ): Promise<ReferralRelationship> {
    const entity = this.repo.create({
      referrerTenantId,
      referredTenantId,
      referralCode,
      level,
      status: 'PENDING',
    });
    return this.repo.save(entity);
  }

  async updateStatus(
    id: string,
    status: ReferralStatus,
    extra?: { activatedAt?: Date; rewardedAt?: Date },
  ): Promise<void> {
    await this.repo.update(id, { status, ...extra });
  }

  async countByReferrer(referrerTenantId: string): Promise<{ direct: number; active: number }> {
    const direct = await this.repo.count({ where: { referrerTenantId } });
    const active = await this.repo.count({
      where: [
        { referrerTenantId, status: 'ACTIVE' },
        { referrerTenantId, status: 'REWARDED' },
      ],
    });
    return { direct, active };
  }

  /** Expire PENDING relationships older than the activation window */
  async expireOldPending(activationWindowDays: number): Promise<number> {
    const cutoff = new Date(Date.now() - activationWindowDays * 24 * 60 * 60 * 1000);
    const result = await this.repo
      .createQueryBuilder()
      .update()
      .set({ status: 'EXPIRED' })
      .where('status = :status AND registered_at < :cutoff', { status: 'PENDING', cutoff })
      .execute();
    return result.affected ?? 0;
  }
}
