import { Injectable, NotFoundException, Logger } from '@nestjs/common';
import { ReviewRepository } from './review.repository';
import { ReviewCardGenerationWorkflow } from '../ai/workflows/review-card-generation.workflow';
import { SubmitReviewDto } from './dto/submit-review.dto';

// Simplified Anki SM-2 algorithm constants
const INTERVALS = [1, 1, 3, 7, 14, 30, 60, 120, 240]; // days
const EASE_FACTOR_DEFAULT = 2.5;
const EASE_FACTOR_MIN = 1.3;

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

  constructor(
    private readonly reviewRepository: ReviewRepository,
    private readonly cardGenerationWorkflow: ReviewCardGenerationWorkflow,
  ) {}

  async getDueCards(userId: string) {
    return this.reviewRepository.findDueCards(userId);
  }

  async submitReview(userId: string, id: string, dto: SubmitReviewDto) {
    const card = await this.reviewRepository.findById(id);
    if (!card) throw new NotFoundException(`Review card ${id} not found`);

    // Anki SM-2 algorithm
    const rating = Number(dto.rating);
    let intervalDays = Number(card.intervalDays) || 1;
    let easeFactor = Number(card.easeFactor) || EASE_FACTOR_DEFAULT;
    let repetitionCount = Number(card.repetitionCount) || 0;
    let lapseCount = Number(card.lapseCount) || 0;
    let scheduleState = (card as any).scheduleState || 'new';

    if (rating >= 3) {
      lapseCount = 0;
      if (scheduleState === 'new' || scheduleState === 'learning') {
        const idx = Math.min(repetitionCount + 1, INTERVALS.length - 1);
        intervalDays = INTERVALS[idx];
      } else {
        intervalDays = Math.round(intervalDays * easeFactor);
      }
      repetitionCount++;
      easeFactor = Math.max(EASE_FACTOR_MIN, easeFactor + (0.1 - (5 - rating) * (0.08 + (5 - rating) * 0.02)));
      scheduleState = 'review';
    } else {
      lapseCount++;
      repetitionCount = 0;
      intervalDays = 1;
      easeFactor = Math.max(EASE_FACTOR_MIN, easeFactor - 0.2);
      scheduleState = 'relearning';
    }

    const nextReviewAt = new Date(Date.now() + intervalDays * 86400000);

    const log = await this.reviewRepository.insertLog({
      userId, reviewCardId: id, rating: dto.rating, responseText: dto.responseText,
    });

    await this.reviewRepository.updateCard(id, {
      status: 'active', nextReviewAt, intervalDays, easeFactor, repetitionCount, lapseCount, scheduleState,
    });

    return { log, nextReviewAt, scheduleState, intervalDays };
  }

  async generateCards(userId: string, input: {
    knowledgeItemTitle: string;
    knowledgeItemContent: string;
    cardCount?: number;
  }) {
    const result = await this.cardGenerationWorkflow.execute({
      userId,
      knowledgeItemTitle: input.knowledgeItemTitle,
      knowledgeItemContent: input.knowledgeItemContent,
      cardCount: input.cardCount,
    });

    const savedCards: any[] = [];
    for (const card of result.cards) {
      const saved = await this.reviewRepository.insertCard({
        userId,
        frontText: card.frontText,
        backText: card.backText,
        difficulty: card.difficulty,
        status: 'active',
        intervalDays: 1,
        easeFactor: EASE_FACTOR_DEFAULT,
        repetitionCount: 0,
        lapseCount: 0,
        scheduleState: 'new',
        nextReviewAt: new Date(),
      });
      savedCards.push(saved);
    }

    return { cards: savedCards, totalCount: result.totalCount };
  }
}
