import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../../database/prisma.service';
import { format, subHours } from 'date-fns';

export interface FarmingCheckResult {
  allowed: boolean;
  reason?: string;
  cooldownUntil?: Date;
}

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

  constructor(private readonly prisma: PrismaService) {}

  /**
   * Verifica se uma tentativa de missão é legítima.
   */
  async checkMissionAttempt(
    childId: string,
    missionId: string,
    attemptDurationSec: number,
  ): Promise<FarmingCheckResult> {
    const today = format(new Date(), 'yyyy-MM-dd');

    // 1. Verificar se já completou hoje (limite diário)
    const todayCompletions = await this.prisma.missionAssignment.count({
      where: {
        childId,
        missionId,
        status: 'COMPLETED',
        completedAt: { gte: new Date(today) },
      },
    });

    const mission = await this.prisma.mission.findUnique({
      where: { id: missionId },
      select: { dailyLimit: true, estimatedMinutes: true },
    });

    if (!mission) {
      return { allowed: false, reason: 'Missão não encontrada' };
    }

    if (todayCompletions >= mission.dailyLimit) {
      return {
        allowed: false,
        reason: `Limite diário atingido (${mission.dailyLimit}x por dia)`,
      };
    }

    // 2. Verificar velocidade suspeita (muito rápido para o conteúdo)
    const minExpectedSec = (mission.estimatedMinutes * 60) * 0.2; // 20% do tempo estimado
    if (attemptDurationSec < minExpectedSec) {
      this.logger.warn(
        `[AntiFarming] Tentativa suspeita: ${childId} completou missão ${missionId} em ${attemptDurationSec}s (mín. esperado: ${minExpectedSec}s)`,
      );
      // Não bloquear, mas reduzir recompensa (sinalizado via log para revisão futura)
    }

    // 3. Verificar padrão de repetição rápida
    const recentAttempts = await this.prisma.attempt.count({
      where: {
        assignment: { childId, missionId },
        startedAt: { gte: subHours(new Date(), 1) },
      },
    });

    if (recentAttempts >= 5) {
      const cooldownUntil = new Date();
      cooldownUntil.setHours(cooldownUntil.getHours() + 1);
      return {
        allowed: false,
        reason: 'Muitas tentativas em pouco tempo. Aguarde antes de tentar novamente.',
        cooldownUntil,
      };
    }

    // 4. Verificar se atingiu limite total de recompensas condicionais hoje
    const wallet = await this.prisma.timeWallet.findUnique({ where: { childId } });
    if (wallet && wallet.earnedConditionalToday >= wallet.dailyConditionalMinutes) {
      return {
        allowed: false,
        reason: 'Você já atingiu o limite de tempo desbloqueável por atividades hoje.',
      };
    }

    return { allowed: true };
  }

  /**
   * Calcula recompensa efetiva considerando anti-farming.
   */
  async calculateEffectiveReward(
    childId: string,
    missionId: string,
    baseRewardMinutes: number,
    score: number,
    attemptDurationSec: number,
  ): Promise<number> {
    const mission = await this.prisma.mission.findUnique({
      where: { id: missionId },
      select: { estimatedMinutes: true },
    });

    if (!mission) return 0;

    // Redução por score baixo
    let multiplier = score;

    // Bônus por tempo razoável (não muito rápido, não muito lento)
    const expectedSec = mission.estimatedMinutes * 60;
    const ratio = attemptDurationSec / expectedSec;
    if (ratio < 0.2) {
      multiplier *= 0.5; // muito rápido = suspeito, 50% de penalidade
    }

    const effective = Math.floor(baseRewardMinutes * multiplier);
    return Math.max(1, effective); // mínimo 1 minuto se passou
  }
}
