import { Injectable } from '@nestjs/common';
import { LearningActivityRepository } from './learning-activity.repository';
import { LearningTrendWorkflow } from '../ai/workflows/learning-trend.workflow';

@Injectable()
export class LearningActivityService {
  constructor(
    private readonly repository: LearningActivityRepository,
    private readonly trendWorkflow: LearningTrendWorkflow,
  ) {}

  async getHeatmap(userId: string, days: number = 365) {
    const from = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
    const to = new Date();
    const activities = await this.repository.findByDateRange(userId, from, to);
    const heatmap: Record<string, number> = {};
    for (const a of activities) {
      const dateStr = a.activityDate instanceof Date
        ? a.activityDate.toISOString().split('T')[0]
        : String(a.activityDate).split('T')[0];
      heatmap[dateStr] = a.durationSeconds;
    }
    return heatmap;
  }

  async getSummary(userId: string) {
    const activities = await this.repository.findAll(userId);
    const totalMinutes = Math.round(
      activities.reduce((s, a) => s + a.durationSeconds, 0) / 60,
    );
    const totalCards = activities.reduce((s, a) => s + a.reviewCount, 0);
    const activeDays = activities.filter((a) => a.durationSeconds > 0).length;
    const dailyAverage = activeDays > 0 ? Math.round(totalMinutes / activeDays) : 0;
    return { totalMinutes, totalCardsReviewed: totalCards, activeDays, dailyAverage };
  }

  async getTrend(userId: string, periodDays: number = 7) {
    const activities = await this.repository.findAll(userId);

    const cutoff = new Date();
    cutoff.setDate(cutoff.getDate() - periodDays);
    const recent = activities.filter((a) =>
      new Date(a.activityDate) >= cutoff
    );

    const previousCutoff = new Date(cutoff);
    previousCutoff.setDate(previousCutoff.getDate() - periodDays);
    const previous = activities.filter((a) => {
      const d = new Date(a.activityDate);
      return d >= previousCutoff && d < cutoff;
    });

    const sum = (items: typeof activities, key: keyof typeof activities[0]) =>
      items.reduce((s, a) => s + (Number(a[key]) || 0), 0);

    const recentTotalMinutes = Math.round(sum(recent, 'durationSeconds') / 60);
    const recentSessions = sum(recent, 'sessionsCount');
    const recentRecall = sum(recent, 'activeRecallCount');
    const recentReview = sum(recent, 'reviewCount');
    const recentAiAnalysis = sum(recent, 'aiAnalysisCount');
    const recentLoops = sum(recent, 'completedLoopCount');
    const recentActiveDays = recent.filter((a) => a.durationSeconds > 0).length;
    const recentDailyAvg = recentActiveDays > 0
      ? Math.round(recentTotalMinutes / recentActiveDays) : 0;
    const recentActivityLevel = recent.length > 0
      ? Math.round(recent.reduce((s, a) => s + a.activityLevel, 0) / recent.length)
      : 0;

    const prevTotalMinutes = Math.round(sum(previous, 'durationSeconds') / 60);

    // Build daily time-series for chart rendering
    const dailySeries = this.buildDailySeries(recent, periodDays);

    const trendInput = {
      userId,
      periodDays,
      totalMinutes: recentTotalMinutes,
      sessionsCount: recentSessions,
      activeRecallCount: recentRecall,
      reviewCount: recentReview,
      aiAnalysisCount: recentAiAnalysis,
      completedLoopCount: recentLoops,
      activityLevel: recentActivityLevel,
      activeDays: recentActiveDays,
      dailyAverage: recentDailyAvg,
      previousPeriod: previous.length > 0 ? {
        totalMinutes: prevTotalMinutes,
        activeRecallCount: sum(previous, 'activeRecallCount'),
        reviewCount: sum(previous, 'reviewCount'),
        activeDays: previous.filter((a) => a.durationSeconds > 0).length,
      } : undefined,
    };

    // AI analysis with 15s timeout fallback
    let aiResult: any = {};
    try {
      aiResult = await Promise.race([
        this.trendWorkflow.execute(trendInput),
        new Promise<any>((_, reject) =>
          setTimeout(() => reject(new Error('AI trend analysis timeout')), 15000)
        ),
      ]);
    } catch (err) {
      aiResult = { periodSummary: 'AI 分析暂不可用', overallScore: 0, overallDirection: 'stable', trends: [], strengths: [], weaknesses: [], recommendations: [], nextFocusAreas: [] };
    }
    return { ...aiResult, dailySeries };
  }

  private buildDailySeries(activities: any[], days: number) {
    const series: { date: string; value: number; label: string }[] = [];
    const now = new Date();
    for (let i = days - 1; i >= 0; i--) {
      const d = new Date(now);
      d.setDate(d.getDate() - i);
      // Use local date string to avoid UTC timezone shift issues
      const dateStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
      const dayActs = activities.filter((a) => {
        const ad = a.activityDate instanceof Date ? a.activityDate : new Date(a.activityDate);
        const adStr = `${ad.getFullYear()}-${String(ad.getMonth() + 1).padStart(2, '0')}-${String(ad.getDate()).padStart(2, '0')}`;
        return adStr === dateStr;
      });
      const minutes = Math.round(dayActs.reduce((s: number, a: any) => s + a.durationSeconds, 0) / 60);
      series.push({
        date: dateStr,
        value: minutes,
        label: `${minutes}分钟`,
      });
    }
    return series;
  }

  /** M8: Upsert daily activity from a reading event. */
  // M8: upsert handled directly by repository in ProcessorService transaction — remove unused wrapper
}
