import { Injectable, Logger } from '@nestjs/common';
import * as crypto from 'crypto';
import { FeatureFlagService } from '../config/feature-flag.service';
import { QuizGenerationSnapshotBuilder } from '../ai-job/quiz-generation-snapshot-builder';
import type { QuizGenerationSnapshotInput } from '../ai-job/quiz-generation-snapshot-builder';
import { AiJobCreationService } from '../ai-job/ai-job-creation.service';
import { UserAiService } from './user-ai.service';
import type { CreateAnalysisJobDto } from './user-ai.dto';

/**
 * M-AI-07-05 / M-AI-07-CLEANUP: Quiz Execution Router
 *
 * 根据 QUIZ_GENERATION_ENGINE_MODE Feature Flag 路由 Quiz 生成请求。
 *   - 'legacy'  → UserAiService.createAnalysisJob()
 *   - 'unified' → SnapshotBuilder → AiJobCreationService
 *
 * 幂等策略（M-AI-07-CLEANUP）：
 *   Priority 1: 客户端显式 idempotencyKey → 直接使用
 *   Priority 2: 规范化内容哈希 + 10min 窗口 → 兼容旧客户端重试
 *   主动重新生成：客户端提供新 idempotencyKey
 */

const FLAG_NAME = 'QUIZ_GENERATION_ENGINE_MODE';

/** 短窗口去重窗口（毫秒），仅用于旧客户端兼容 */
const IDEMPOTENCY_WINDOW_MS = 10 * 60 * 1000; // 10 minutes

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

  constructor(
    private readonly featureFlag: FeatureFlagService,
    private readonly snapshotBuilder: QuizGenerationSnapshotBuilder,
    private readonly creationService: AiJobCreationService,
    private readonly legacyService: UserAiService,
  ) {}

  async generateQuiz(userId: string, dto: CreateAnalysisJobDto) {
    // M-MEMBER-01-CLOSE-01A: 额度预占已由 UserAiController 集中处理，此处不再重复 reserve

    const useUnified = await this.shouldUseUnified(userId);

    if (!useUnified) {
      this.logger.log(`QUIZ_GENERATION_ENGINE_MODE=legacy for userId=${userId}`);
      return this.legacyService.createAnalysisJob(userId, dto);
    }

    this.logger.log(`QUIZ_GENERATION_ENGINE_MODE=unified for userId=${userId}`);

    // ═════════════════════════════════════════════════════════
    // 幂等标识解析（M-AI-07-CLEANUP）
    // ═════════════════════════════════════════════════════════

    let effectiveId: string;
    let idSource: 'client' | 'compatibility_window';

    if (dto.idempotencyKey) {
      // Priority 1: 客户端显式操作标识
      effectiveId = dto.idempotencyKey;
      idSource = 'client';
    } else {
      // Priority 2: 规范化内容哈希 + 短窗口（兼容旧客户端重试）
      const contentKey = this.buildContentKey(dto);
      const windowTs = Math.floor(Date.now() / IDEMPOTENCY_WINDOW_MS);
      effectiveId = `${contentKey}:w${windowTs}`;
      idSource = 'compatibility_window';
    }

    const submissionId = effectiveId;
    const idempotencyKey = `quiz-generation:${effectiveId}`;

    // ═════════════════════════════════════════════════════════
    // Snapshot + Job 创建
    // ═════════════════════════════════════════════════════════

    const snapshotInput: QuizGenerationSnapshotInput = {
      userId,
      targetType: dto.targetType,
      targetId: dto.targetId,
      submissionId,
      questionCount: dto.questionCount,
      questionTypes: dto.questionTypes,
      difficultyLevel: dto.difficultyLevel,
      knowledgePointIds: dto.knowledgePointIds,
    };

    const snapshot = await this.snapshotBuilder.build(snapshotInput);

    const job = await this.creationService.createJob({
      userId,
      jobType: 'quiz_generation',
      triggerType: 'user_api',
      targetType: dto.targetType,
      targetId: dto.targetId,
      idempotencyKey,
      retrySnapshotContent: snapshot as unknown as Record<string, unknown>,
    });

    const isIdempotentHit = job.createdAt?.getTime?.() !== undefined &&
      (Date.now() - new Date(job.createdAt).getTime()) > 1000;

    this.logger.log(
      `Quiz Unified: jobId=${job.id} userId=${userId} ` +
      `idSource=${idSource} idempotencyHit=${isIdempotentHit} ` +
      `targetType=${dto.targetType} targetId=${dto.targetId} ` +
      `questionCount=${snapshot.snapshot.questionCount}`,
    );

    return {
      jobId: job.id,
      status: 'queued',
      engineMode: 'unified' as const,
      lifecycleStatus: 'queued',
      planId: undefined,
    };
  }

  // ── Private ──

  /**
   * 构建确定性内容键（SHA-256 前 24 字符）。
   *
   * 规范化参数：targetType, targetId, questionCount, questionTypes(sorted), difficultyLevel。
   * 不包含：时间戳、随机值、完整学习资料、PII。
   */
  private buildContentKey(dto: CreateAnalysisJobDto): string {
    const types = (dto.questionTypes ?? []).slice().sort().join(',');
    const normalized = [
      dto.targetType,
      dto.targetId,
      String(dto.questionCount ?? 5),
      types || 'choice,fill,judge',
      dto.difficultyLevel ?? 'medium',
    ].join('|');
    return crypto.createHash('sha256').update(normalized).digest('hex').substring(0, 24);
  }

  private async shouldUseUnified(userId: string): Promise<boolean> {
    try {
      return await this.featureFlag.isEnabled(FLAG_NAME, userId);
    } catch (err: any) {
      this.logger.warn(`FeatureFlag query failed, falling back to legacy: ${err.message}`);
      return false;
    }
  }
}
