import { Injectable, Logger, Optional } from '@nestjs/common';
import { PrismaService } from '../../infrastructure/database/prisma.service';
import { EventBusService } from '../../common/event-bus/event-bus.service';
import { StreakUpdatedEvent } from '../../common/events/streak-updated.event';

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

  constructor(
    private readonly prisma: PrismaService,
    @Optional() private readonly eventBus?: EventBusService,
  ) {}

  /** Calculate streak from daily activity */
  async getStreak(userId: string): Promise<{ currentStreak: number; longestStreak: number }> {
    const activities = await this.prisma.dailyLearningActivity.findMany({
      where: { userId },
      orderBy: { activityDate: 'desc' },
      select: { activityDate: true },
      take: 365,
    });

    if (activities.length === 0) return { currentStreak: 0, longestStreak: 0 };

    const seen = new Set<string>();
    const dates: string[] = [];
    for (const a of activities) {
      const d = new Date(a.activityDate).toISOString().slice(0, 10);
      if (!seen.has(d)) { seen.add(d); dates.push(d); }
    }

    let currentStreak = dates.length > 0 ? 1 : 0;
    let longestStreak = currentStreak;
    let streak = currentStreak;

    for (let i = 1; i < dates.length; i++) {
      const prev = new Date(dates[i - 1]);
      const curr = new Date(dates[i]);
      const diffDays = Math.round((prev.getTime() - curr.getTime()) / 86400000);
      if (diffDays === 1) {
        streak++;
        longestStreak = Math.max(longestStreak, streak);
      } else if (diffDays === 0) {
        // same day, skip
      } else {
        break; // gap found — stop counting current streak
      }
    }
    currentStreak = streak;

    // Publish event for downstream consumers
    try { this.eventBus?.publish(new StreakUpdatedEvent(userId, currentStreak, longestStreak)); } catch {}

    return { currentStreak, longestStreak };
  }

  /** Get learning recommendation based on mastery */
  async getRecommendations(userId: string): Promise<{ type: string; title: string; reason: string }[]> {
    const recommendations: { type: string; title: string; reason: string }[] = [];

    // Find open focus items
    const focusCount = await this.prisma.focusItem.count({
      where: { userId, status: 'open' },
    });

    if (focusCount > 0) {
      recommendations.push({
        type: 'focus', title: `${focusCount} 个待巩固项`, reason: '巩固薄弱环节，提升掌握度',
      });
    }

    // Find due review cards
    const now = new Date();
    const dueCards = await this.prisma.reviewCard.count({
      where: { userId, nextReviewAt: { lte: now }, status: 'active' },
    });

    if (dueCards > 0) {
      recommendations.push({
        type: 'review', title: `${dueCards} 张复习卡到期`, reason: '间隔复习，巩固长期记忆',
      });
    }

    // Suggest new knowledge items if no pending items
    if (focusCount === 0 && dueCards === 0) {
      const itemsCount = await this.prisma.knowledgeItem.count({
        where: { userId, deletedAt: null, learnable: true },
      });
      if (itemsCount > 0) {
        recommendations.push({
          type: 'learn', title: `${itemsCount} 个可学习知识点`, reason: '继续拓展知识库',
        });
      } else {
        recommendations.push({
          type: 'import', title: '导入新资料', reason: '开始学习新内容',
        });
      }
    }

    return recommendations;
  }
}
