import { Injectable, Logger, BadRequestException } from '@nestjs/common';
import * as crypto from 'crypto';
import { FeatureFlagService } from '../config/feature-flag.service';
import { FeynmanSnapshotBuilder } from '../ai-job/feynman-snapshot-builder';
import type { FeynmanSnapshotInput } from '../ai-job/feynman-snapshot-builder';
import { AiJobCreationService } from '../ai-job/ai-job-creation.service';
import { JobDefinitionRegistry } from '../ai-job/job-definition-registry';
import { AiAnalysisService } from './ai-analysis.service';

/**
 * M-AI-05-05: Feynman Execution Router
 *
 * 根据 FEYNMAN_ENGINE_MODE Feature Flag 决定 Feynman 评估的执行分支：
 *   - 'legacy'  → 原 AiAnalysisService.evaluateFeynman() 路径
 *   - 'unified' → FeynmanSnapshotBuilder → AiJobCreationService → Unified Job Engine
 *
 * 设计约束（契约 §10）：
 *   - 分支判断集中在 Router，不散落在 Controller/Service/Worker
 *   - 支持用户白名单（通过 FeatureFlagService）
 *   - 默认 legacy（Feature Flag 不存在或 disabled 时）
 *   - Unified 失败不得自动调用 Legacy
 *   - 同一请求只能执行一个引擎
 */

const FLAG_NAME = 'FEYNMAN_ENGINE_MODE';

/** Feynman HTTP 请求体（与 AiAnalysisController 保持一致） */
export interface FeynmanEvaluateInput {
  knowledgeItemTitle: string;
  knowledgeItemContent: string;
  userExplanation: string;
  sessionId?: string;
  answerId?: string;
}

/** Unified 模式扩展响应 */
export interface FeynmanUnifiedResponse {
  jobId: string;
  status: string;
  engineMode: 'unified';
  lifecycleStatus: string;
}

/** Legacy 兼容响应 */
export interface FeynmanLegacyResponse {
  jobId: string;
  status: string;
}

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

  constructor(
    private readonly featureFlag: FeatureFlagService,
    private readonly snapshotBuilder: FeynmanSnapshotBuilder,
    private readonly creationService: AiJobCreationService,
    private readonly registry: JobDefinitionRegistry,
    private readonly legacyService: AiAnalysisService,
  ) {}

  /**
   * 路由 Feynman 评估请求。
   *
   * @param userId - 请求用户 ID
   * @param input - 请求体（knowledgeItemTitle/content/explanation + 可选的 sessionId/answerId）
   * @param knowledgeItemId - 知识点 ID（由 Controller 从请求体获取或后续客户端传入）
   * @returns Legacy 或 Unified 响应
   */
  async evaluateFeynman(
    userId: string,
    input: FeynmanEvaluateInput,
    knowledgeItemId?: string,
  ): Promise<FeynmanLegacyResponse | FeynmanUnifiedResponse> {
    // 1. 基本参数校验（与 Legacy 一致）
    if (!input.knowledgeItemTitle?.trim()) {
      throw new BadRequestException('knowledgeItemTitle is required');
    }
    if (!input.knowledgeItemContent?.trim()) {
      throw new BadRequestException('knowledgeItemContent is required');
    }
    if (!input.userExplanation?.trim()) {
      throw new BadRequestException('userExplanation is required');
    }

    // 2. 检查 Feature Flag
    const useUnified = await this.shouldUseUnified(userId);

    if (!useUnified) {
      // ── Legacy 路径 ──
      return this.legacyService.evaluateFeynman(userId, input);
    }

    // ═════════════════════════════════════════════════════════
    // ── Unified 路径 ──
    // ═════════════════════════════════════════════════════════

    // 3. 确定 knowledgeItemId
    //    当前请求体不含此字段（契约 U-2），使用传入值或占位符
    //    M-AI-05-07 及后续客户端升级后可传入真实 ID
    const resolvedKnowledgeItemId = knowledgeItemId || 'unknown';

    // 4. 确定稳定 submissionId（幂等键来源）
    const submissionId = this.resolveSubmissionId(input);

    // 5. 构造 idempotencyKey
    const idempotencyKey = `feynman:${submissionId}`;

    // 6. 构建 Snapshot
    const snapshotInput: FeynmanSnapshotInput = {
      userId,
      knowledgeItemId: resolvedKnowledgeItemId,
      knowledgeItemTitle: input.knowledgeItemTitle,
      knowledgeItemContent: input.knowledgeItemContent,
      userExplanation: input.userExplanation,
      submissionId,
      sessionId: input.sessionId,
      answerId: input.answerId,
    };

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

    // 7. 通过 AiJobCreationService 创建 Job（原子：Job + Snapshot + Outbox）
    const result = await this.creationService.createJob({
      userId,
      jobType: 'feynman_evaluation',
      triggerType: 'user_api',
      targetType: 'knowledge_item',
      targetId: resolvedKnowledgeItemId,
      idempotencyKey,
      retrySnapshotContent: snapshot as unknown as Record<string, unknown>,
    });

    this.logger.log(
      `Feynman Unified: jobId=${result.id} userId=${userId} ` +
      `submissionId=${submissionId} idempotencyKey=${idempotencyKey}`,
    );

    // 8. 返回兼容响应（不删除旧字段，新增可选字段）
    return {
      jobId: result.id,
      status: 'queued',
      engineMode: 'unified',
      lifecycleStatus: 'queued',
    };
  }

  // ── Private Helpers ──

  /**
   * 判断是否应使用 Unified 引擎。
   *
   * FeatureFlag 查询失败 → 安全回退到 legacy。
   */
  private async shouldUseUnified(userId: string): Promise<boolean> {
    try {
      const enabled = await this.featureFlag.isEnabled(FLAG_NAME, userId);
      this.logger.log(
        `FEYNMAN_ENGINE_MODE=${enabled ? 'unified' : 'legacy'} for userId=${userId}`,
      );
      return enabled;
    } catch (err: any) {
      this.logger.warn(
        `FeatureFlag query failed, falling back to legacy: ${err.message}`,
      );
      return false;
    }
  }

  /**
   * 从请求参数解析稳定 submissionId。
   *
   * 优先级：
   *   1. sessionId + answerId 组合（如都存在）
   *   2. sessionId（如仅 sessionId 存在）
   *   3. 基于 content 的 hash 回退（保证相同内容 → 相同 ID）
   */
  private resolveSubmissionId(input: FeynmanEvaluateInput): string {
    if (input.sessionId && input.answerId) {
      return `${input.sessionId}:${input.answerId}`;
    }
    if (input.sessionId) {
      return input.sessionId;
    }
    // 回退：基于内容 hash 的 submissionId（相同输入 → 相同 key）
    const contentKey = [
      input.knowledgeItemTitle,
      input.knowledgeItemContent,
      input.userExplanation,
    ].join('|');
    return crypto.createHash('sha256').update(contentKey).digest('hex').substring(0, 16);
  }
}
