import { Injectable, Logger } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, LessThan } from 'typeorm';
import { Payout, PayoutStatus } from '../modules/payments/entities/payout.entity';
import { PayoutService } from '../modules/payments/payout.service';
import { NotificationsService } from '../modules/notifications/notifications.service';

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

  constructor(
    @InjectRepository(Payout)
    private readonly payoutRepo: Repository<Payout>,
    private readonly payoutService: PayoutService,
    private readonly notificationsService: NotificationsService,
  ) {}

  /**
   * Process pending payouts every 6 hours
   * Ensures sellers receive their earnings on schedule
   */
  @Cron(CronExpression.EVERY_6_HOURS)
  async processPendingPayouts(): Promise<void> {
    this.logger.log('Processing pending payouts...');

    const pendingPayouts = await this.payoutRepo.find({
      where: { status: PayoutStatus.PENDING },
      order: { createdAt: 'ASC' },
    });

    if (pendingPayouts.length === 0) {
      this.logger.log('No pending payouts to process');
      return;
    }

    this.logger.log(`Processing ${pendingPayouts.length} pending payouts`);

    for (const payout of pendingPayouts) {
      try {
        await this.payoutService.processPayout(payout.id);
        this.logger.log(`Payout ${payout.id} processed successfully`);

        await this.notificationsService.sendToUser(payout.sellerId, {
          type: 'payout_completed',
          data: {
            payoutId: payout.id,
            amount: payout.amount,
            currency: payout.currency,
            processedAt: new Date().toISOString(),
          },
        });
      } catch (error) {
        this.logger.error(`Failed to process payout ${payout.id}: ${error.message}`);

        payout.status = PayoutStatus.FAILED;
        payout.metadata = { ...payout.metadata, error: error.message };
        await this.payoutRepo.save(payout);
      }
    }
  }

  /**
   * Auto-generate weekly payouts for eligible sellers
   * Runs every Monday at 9:00 AM
   */
  @Cron('0 9 * * 1')
  async generateWeeklyPayouts(): Promise<void> {
    this.logger.log('Generating weekly payouts...');

    // Get sellers with earnings above minimum threshold ($50)
    const minimumPayoutAmount = 50;

    // This would query completed transactions and calculate seller earnings
    // For now, placeholder implementation
    this.logger.log(`Weekly payout generation completed. Minimum threshold: $${minimumPayoutAmount}`);
  }

  /**
   * Retry failed payouts (up to 3 attempts)
   * Runs every 12 hours
   */
  @Cron(CronExpression.EVERY_12_HOURS)
  async retryFailedPayouts(): Promise<void> {
    this.logger.log('Retrying failed payouts...');

    const failedPayouts = await this.payoutRepo.find({
      where: {
        status: PayoutStatus.FAILED,
        createdAt: LessThan(new Date(Date.now() - 6 * 60 * 60 * 1000)), // At least 6 hours old
      },
    });

    for (const payout of failedPayouts) {
      const retryCount = payout.metadata?.retryCount || 0;
      if (retryCount >= 3) {
        this.logger.warn(`Payout ${payout.id} exceeded max retry attempts`);
        continue;
      }

      try {
        payout.status = PayoutStatus.PENDING;
        payout.metadata = { ...payout.metadata, retryCount: retryCount + 1 };
        await this.payoutRepo.save(payout);

        this.logger.log(`Retrying payout ${payout.id} (attempt ${retryCount + 1})`);
      } catch (error) {
        this.logger.error(`Failed to retry payout ${payout.id}: ${error.message}`);
      }
    }
  }
}