import { Injectable, Logger } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, LessThan } from 'typeorm';
import { KYCVerification, KYCStatus } from '../modules/kyc/entities/kyc-verification.entity';
import { NotificationsService } from '../modules/notifications/notifications.service';

@Injectable()
export class KYCReviewReminderCron {
  private readonly logger = new Logger(KYCReviewReminderCron.name);

  constructor(
    @InjectRepository(KYCVerification)
    private readonly kycRepo: Repository<KYCVerification>,
    private readonly notificationsService: NotificationsService,
  ) {}

  /**
   * Runs every hour to check for KYC submissions pending review
   * Sends reminder notifications to admin team if reviews are stale
   */
  @Cron(CronExpression.EVERY_HOUR)
  async checkPendingReviews(): Promise<void> {
    this.logger.log('Checking for pending KYC reviews...');

    const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);

    const staleSubmissions = await this.kycRepo.find({
      where: {
        status: KYCStatus.UNDER_REVIEW,
        submittedAt: LessThan(twentyFourHoursAgo),
      },
      relations: ['documents'],
    });

    if (staleSubmissions.length === 0) {
      this.logger.log('No stale KYC submissions found');
      return;
    }

    this.logger.warn(`Found ${staleSubmissions.length} KYC submissions pending review for over 24 hours`);

    // Notify admin team about stale reviews
    await this.notificationsService.sendToAdmins({
      type: 'kyc_review_reminder',
      data: {
        count: staleSubmissions.length,
        submissions: staleSubmissions.map(s => ({
          id: s.id,
          userId: s.userId,
          type: s.type,
          submittedAt: s.submittedAt,
          daysPending: Math.floor((Date.now() - new Date(s.submittedAt).getTime()) / (1000 * 60 * 60 * 24)),
        })),
      },
    });

    // Send reminder to individual users if review is taking too long (>72 hours)
    const seventyTwoHoursAgo = new Date(Date.now() - 72 * 60 * 60 * 1000);
    const veryStaleSubmissions = staleSubmissions.filter(
      s => new Date(s.submittedAt) < seventyTwoHoursAgo,
    );

    for (const submission of veryStaleSubmissions) {
      await this.notificationsService.sendToUser(submission.userId, {
        type: 'kyc_review_delayed',
        data: {
          message: 'Your verification is taking longer than expected. We appreciate your patience.',
          submittedAt: submission.submittedAt,
        },
      });
    }

    this.logger.log(`Sent ${veryStaleSubmissions.length} delayed review notifications to users`);
  }

  /**
   * Daily cleanup of abandoned KYC submissions (started but never finalized)
   * Runs at 3:00 AM every day
   */
  @Cron('0 3 * * *')
  async cleanupAbandonedSubmissions(): Promise<void> {
    this.logger.log('Cleaning up abandoned KYC submissions...');

    const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);

    const abandonedSubmissions = await this.kycRepo.find({
      where: {
        status: KYCStatus.PENDING,
        createdAt: LessThan(sevenDaysAgo),
      },
    });

    if (abandonedSubmissions.length > 0) {
      // Soft delete by marking as expired
      for (const submission of abandonedSubmissions) {
        submission.status = KYCStatus.REJECTED;
        submission.rejectionReason = 'Submission expired - incomplete after 7 days';
        await this.kycRepo.save(submission);
      }

      this.logger.log(`Cleaned up ${abandonedSubmissions.length} abandoned KYC submissions`);
    }
  }
}