/**
 * Claude Agent Service V2 - 集成策略引擎
 *
 * 相比V1的主要改进：
 * 1. 集成策略引擎，按老板定义的流程引导用户
 * 2. 对话有明确的阶段和目标
 * 3. 自动收集和保存用户信息
 * 4. 在关键节点自动调用必需的工具
 * 5. 支持老用户识别和个性化破冰
 *
 * @deprecated 已被 CoordinatorAgentService 取代。
 * 新架构使用多 Agent 协作模式（Coordinator + 6 个专家 Agent），提供更灵活的对话能力。
 * 参见 infrastructure/agents/coordinator/coordinator-agent.service.ts
 */

import { Injectable, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import Anthropic from '@anthropic-ai/sdk';
import { ImmigrationToolsService } from './tools/immigration-tools.service';
import { TokenUsageService } from './token-usage.service';
import { buildSystemPrompt, SystemPromptConfig } from './prompts/system-prompt';
import { KnowledgeClientService } from '../knowledge/knowledge-client.service';
import { intentClassifier, IntentResult, IntentType } from './intent-classifier';
import { responseGate } from './response-gate';
import {
  StrategyEngineService,
  ConsultingState,
} from './strategy/strategy-engine.service';
import {
  StageId,
  getStageById,
  DEFAULT_CONSULTING_STRATEGY,
} from './strategy/default-strategy';

export interface FileAttachment {
  id: string;
  originalName: string;
  mimeType: string;
  type: 'image' | 'document' | 'audio' | 'video' | 'other';
  size: number;
  downloadUrl?: string;
  thumbnailUrl?: string;
}

export interface ConversationContext {
  userId: string;
  conversationId: string;
  userMemory?: string[];
  previousMessages?: Array<{
    role: 'user' | 'assistant';
    content: string;
    attachments?: FileAttachment[];
  }>;
  // V2新增：咨询状态
  consultingState?: ConsultingState;
  // V2新增：用户设备信息（用于新用户破冰）
  deviceInfo?: {
    ip?: string;
    userAgent?: string;
    fingerprint?: string;
  };
}

export interface StreamChunk {
  type: 'text' | 'tool_use' | 'tool_result' | 'end' | 'stage_change' | 'state_update' | 'error';
  content?: string;
  toolName?: string;
  toolInput?: Record<string, unknown>;
  toolResult?: unknown;
  // V2新增
  stageName?: string;
  newState?: ConsultingState;
  // Token usage (returned with 'end' or 'error' chunk)
  inputTokens?: number;
  outputTokens?: number;
  // Error info (only for 'error' type)
  errorMessage?: string;
}

@Injectable()
export class ClaudeAgentServiceV2 implements OnModuleInit {
  private client: Anthropic;
  private systemPromptConfig: SystemPromptConfig;

  constructor(
    private configService: ConfigService,
    private immigrationToolsService: ImmigrationToolsService,
    private knowledgeClient: KnowledgeClientService,
    private tokenUsageService: TokenUsageService,
    private strategyEngine: StrategyEngineService,
  ) {}

  onModuleInit() {
    const baseUrl = this.configService.get<string>('ANTHROPIC_BASE_URL');
    const isProxyUrl = baseUrl && (baseUrl.includes('67.223.119.33') || baseUrl.match(/^\d+\.\d+\.\d+\.\d+/));

    if (isProxyUrl) {
      console.log(`Using Anthropic proxy (TLS verification disabled): ${baseUrl}`);
      process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
    }

    this.client = new Anthropic({
      apiKey: this.configService.get<string>('ANTHROPIC_API_KEY'),
      baseURL: baseUrl || undefined,
    });

    this.systemPromptConfig = {
      identity: '专业、友善、耐心的香港移民顾问',
      conversationStyle: '专业但不生硬，用简洁明了的语言解答',
    };
  }

  /**
   * 初始化或获取咨询状态
   */
  initializeOrGetState(context: ConversationContext): ConsultingState {
    if (context.consultingState) {
      return context.consultingState;
    }
    return this.strategyEngine.initializeState();
  }

  /**
   * 发送消息并获取流式响应 - V2版本
   *
   * 核心改进：
   * 1. 在对话开始时检查用户历史（老用户/新用户）
   * 2. 根据当前阶段注入行为指令
   * 3. 自动判断阶段转移
   * 4. 从对话中提取用户信息
   */
  async *sendMessage(
    message: string,
    context: ConversationContext,
    attachments?: FileAttachment[],
  ): AsyncGenerator<StreamChunk> {
    // ========== 1. 初始化咨询状态 ==========
    let state = this.initializeOrGetState(context);
    const isFirstMessage = !context.previousMessages || context.previousMessages.length === 0;

    console.log(`[ClaudeAgentV2] Stage: ${state.currentStageId}, Turn: ${state.stageTurnCount}, IsFirst: ${isFirstMessage}`);

    // ========== 2. 检查阶段转移 ==========
    if (!isFirstMessage) {
      const transitionResult = await this.strategyEngine.evaluateTransition(state, message);
      if (transitionResult.shouldTransition && transitionResult.targetStageId) {
        console.log(`[ClaudeAgentV2] Stage transition: ${state.currentStageId} -> ${transitionResult.targetStageId} (${transitionResult.reason})`);
        state = this.strategyEngine.transitionToStage(state, transitionResult.targetStageId);
        yield {
          type: 'stage_change',
          stageName: getStageById(transitionResult.targetStageId)?.name,
        };
      }
    }

    // ========== 3. 意图分类（保留原有能力） ==========
    const conversationHistory = context.previousMessages?.map(msg => ({
      role: msg.role,
      content: msg.content,
    })) || [];
    const intent = intentClassifier.classify(message, conversationHistory);

    console.log(`[ClaudeAgentV2] Intent: ${intent.type}, Stage: ${state.currentStageId}`);

    // ========== 4. 构建增强的System Prompt ==========
    const tools = this.immigrationToolsService.getTools();
    const accumulatedExperience = await this.getAccumulatedExperience(message);

    // 构建阶段引导
    const stageGuidance = this.strategyEngine.buildStageGuidance(state);

    // 构建设备信息提示（用于新用户破冰）
    const deviceContext = this.buildDeviceContext(context, isFirstMessage);

    const dynamicConfig: SystemPromptConfig = {
      ...this.systemPromptConfig,
      accumulatedExperience,
      intentHint: intent,
    };
    let systemPrompt = buildSystemPrompt(dynamicConfig);

    // 注入策略引导到System Prompt
    systemPrompt = this.injectStrategyGuidance(systemPrompt, stageGuidance, deviceContext, state);

    // ========== 5. 构建消息数组 ==========
    const messages: Anthropic.MessageParam[] = [];

    if (context.previousMessages) {
      for (const msg of context.previousMessages) {
        if (msg.attachments && msg.attachments.length > 0 && msg.role === 'user') {
          const multimodalContent = await this.buildMultimodalContent(msg.content, msg.attachments);
          messages.push({ role: msg.role, content: multimodalContent });
        } else {
          messages.push({ role: msg.role, content: msg.content });
        }
      }
    }

    if (attachments && attachments.length > 0) {
      const multimodalContent = await this.buildMultimodalContent(message, attachments);
      messages.push({ role: 'user', content: multimodalContent });
    } else {
      messages.push({ role: 'user', content: message });
    }

    // ========== 6. 调用Claude API ==========
    const maxIterations = 10;
    let iterations = 0;
    const maxTokens = this.calculateMaxTokens(intent, state);

    const systemWithCache: Anthropic.TextBlockParam[] = [
      {
        type: 'text',
        text: systemPrompt,
        cache_control: { type: 'ephemeral' },
      },
    ];

    let fullResponseText = '';
    const startTime = Date.now();
    let totalInputTokens = 0;
    let totalOutputTokens = 0;
    let totalCacheCreationTokens = 0;
    let totalCacheReadTokens = 0;
    let toolCallCount = 0;

    while (iterations < maxIterations) {
      iterations++;

      try {
        const stream = await this.client.messages.stream({
          model: 'claude-sonnet-4-20250514',
          max_tokens: maxTokens,
          system: systemWithCache,
          messages,
          tools: tools as Anthropic.Tool[],
        });

        let currentToolUse: {
          id: string;
          name: string;
          inputJson: string;
          input: Record<string, unknown>;
        } | null = null;

        const toolUses: Array<{ id: string; name: string; input: Record<string, unknown> }> = [];
        const assistantContent: Anthropic.ContentBlockParam[] = [];

        for await (const event of stream) {
          if (event.type === 'content_block_start') {
            if (event.content_block.type === 'tool_use') {
              currentToolUse = {
                id: event.content_block.id,
                name: event.content_block.name,
                inputJson: '',
                input: {},
              };
            }
          } else if (event.type === 'content_block_delta') {
            if (event.delta.type === 'text_delta') {
              fullResponseText += event.delta.text;
              yield { type: 'text', content: event.delta.text };
            } else if (event.delta.type === 'input_json_delta' && currentToolUse) {
              currentToolUse.inputJson += event.delta.partial_json || '';
            }
          } else if (event.type === 'content_block_stop') {
            if (currentToolUse) {
              try {
                currentToolUse.input = JSON.parse(currentToolUse.inputJson || '{}');
              } catch {
                currentToolUse.input = {};
              }

              toolUses.push({
                id: currentToolUse.id,
                name: currentToolUse.name,
                input: currentToolUse.input,
              });

              yield {
                type: 'tool_use',
                toolName: currentToolUse.name,
                toolInput: currentToolUse.input,
              };

              currentToolUse = null;
            }
          }
        }

        const finalMsg = await stream.finalMessage();

        if (finalMsg.usage) {
          totalInputTokens += finalMsg.usage.input_tokens || 0;
          totalOutputTokens += finalMsg.usage.output_tokens || 0;
          const usage = finalMsg.usage as unknown as Record<string, number>;
          totalCacheCreationTokens += usage.cache_creation_input_tokens || 0;
          totalCacheReadTokens += usage.cache_read_input_tokens || 0;
        }

        // 如果没有工具调用，完成
        if (toolUses.length === 0) {
          // ========== 7. 回复后处理 ==========

          // 7.1 质量门控
          if (fullResponseText) {
            const gateResult = responseGate.check(fullResponseText, intent, message);
            console.log(`[ClaudeAgentV2] Response gate: passed=${gateResult.passed}, length=${fullResponseText.length}`);
          }

          // 7.2 提取用户信息
          const newInfo = await this.strategyEngine.extractUserInfo(
            message,
            fullResponseText,
            state.collectedInfo,
          );
          if (Object.keys(newInfo).length > 0) {
            console.log(`[ClaudeAgentV2] Extracted user info:`, newInfo);
            state = this.strategyEngine.updateCollectedInfo(state, newInfo);
          }

          // 7.3 如果在评估阶段且信息充足，执行评估
          if (state.currentStageId === StageId.ASSESSMENT && !state.assessmentResult) {
            const coreInfoCount = ['age', 'education', 'workYears', 'annualIncome']
              .filter(key => state.collectedInfo[key] !== undefined).length;
            if (coreInfoCount >= 3) {
              const assessmentResult = await this.strategyEngine.performAssessment(state.collectedInfo);
              state = this.strategyEngine.setAssessmentResult(state, assessmentResult);
              console.log(`[ClaudeAgentV2] Assessment completed:`, assessmentResult);
            }
          }

          // 7.4 增加轮次计数
          state = this.strategyEngine.incrementTurnCount(state);

          // 7.5 记录Token使用量
          const latencyMs = Date.now() - startTime;
          this.tokenUsageService.recordUsage({
            userId: context.userId,
            conversationId: context.conversationId,
            model: 'claude-sonnet-4-20250514',
            inputTokens: totalInputTokens,
            outputTokens: totalOutputTokens,
            cacheCreationTokens: totalCacheCreationTokens,
            cacheReadTokens: totalCacheReadTokens,
            intentType: intent.type,
            toolCalls: toolCallCount,
            responseLength: fullResponseText.length,
            latencyMs,
          }).catch(err => console.error('[ClaudeAgentV2] Failed to record token usage:', err));

          // 7.6 返回更新后的状态
          yield { type: 'state_update', newState: state };
          yield { type: 'end', inputTokens: totalInputTokens, outputTokens: totalOutputTokens };
          return;
        }

        // 处理工具调用
        toolCallCount += toolUses.length;

        for (const block of finalMsg.content) {
          if (block.type === 'text') {
            assistantContent.push({ type: 'text', text: block.text });
          } else if (block.type === 'tool_use') {
            assistantContent.push({
              type: 'tool_use',
              id: block.id,
              name: block.name,
              input: block.input as Record<string, unknown>,
            });
          }
        }

        messages.push({ role: 'assistant', content: assistantContent });

        const toolResults: Anthropic.ToolResultBlockParam[] = [];
        for (const toolUse of toolUses) {
          const result = await this.immigrationToolsService.executeTool(
            toolUse.name,
            toolUse.input,
            context,
          );

          yield {
            type: 'tool_result',
            toolName: toolUse.name,
            toolResult: result,
          };

          toolResults.push({
            type: 'tool_result',
            tool_use_id: toolUse.id,
            content: JSON.stringify(result),
          });

          // 如果是get_user_context工具，从结果中提取已有信息
          if (toolUse.name === 'get_user_context' && result) {
            const userContextResult = result as { memories?: Array<{ type: string; content: string }> };
            if (userContextResult.memories && userContextResult.memories.length > 0) {
              console.log(`[ClaudeAgentV2] Found existing user memories:`, userContextResult.memories.length);
              // 可以从记忆中提取已知信息更新state
            }
          }
        }

        messages.push({ role: 'user', content: toolResults });

      } catch (error) {
        console.error('[ClaudeAgentV2] Claude API error:', error);

        // Record partial token usage even on error (for cost tracking)
        if (totalInputTokens > 0 || totalOutputTokens > 0) {
          const latencyMs = Date.now() - startTime;
          this.tokenUsageService.recordUsage({
            userId: context.userId,
            conversationId: context.conversationId,
            model: 'claude-sonnet-4-20250514',
            inputTokens: totalInputTokens,
            outputTokens: totalOutputTokens,
            cacheCreationTokens: totalCacheCreationTokens,
            cacheReadTokens: totalCacheReadTokens,
            intentType: intent?.type || 'UNKNOWN',
            toolCalls: toolCallCount,
            responseLength: fullResponseText.length,
            latencyMs,
          }).catch(err => console.error('[ClaudeAgentV2] Failed to record partial token usage:', err));
        }

        // Yield error chunk with partial tokens before throwing
        yield {
          type: 'error',
          inputTokens: totalInputTokens,
          outputTokens: totalOutputTokens,
          errorMessage: error instanceof Error ? error.message : 'Unknown error',
        };
        throw error;
      }
    }

    console.error('[ClaudeAgentV2] Tool loop exceeded maximum iterations');
    yield { type: 'end', inputTokens: totalInputTokens, outputTokens: totalOutputTokens };
  }

  /**
   * 注入策略引导到System Prompt
   */
  private injectStrategyGuidance(
    basePrompt: string,
    stageGuidance: string,
    deviceContext: string,
    state: ConsultingState,
  ): string {
    const strategy = this.strategyEngine.getStrategy();
    const stage = this.strategyEngine.getCurrentStage(state);

    const injectedContent = `
${basePrompt}

================================================================================
【重要】咨询流程控制 - 你必须按照以下策略执行
================================================================================

${stageGuidance}

${deviceContext}

## 工具调用要求
当前阶段建议使用的工具：
${stage.suggestedTools.map(t => {
  const priorityLabel = t.priority === 'required' ? '【必须调用】' : t.priority === 'recommended' ? '【建议调用】' : '【可选】';
  return `- ${priorityLabel} ${t.toolName}: ${t.description}\n  触发条件: ${t.triggerCondition}`;
}).join('\n')}

## 非移民话题处理
如果用户询问与香港移民无关的问题：
1. 调用 check_off_topic 工具确认是否离题
2. 如果确认离题，礼貌拒绝并引导回移民话题
3. 示例回复："抱歉，我是专门的香港移民咨询顾问，对于[用户问题的领域]我不太了解。如果您有香港移民相关的问题，我很乐意帮您解答。"

## 专家对接信息
- 人类专家微信: ${strategy.expertContact.wechat}
- 专家电话: ${strategy.expertContact.phone}
- 工作时间: ${strategy.expertContact.workingHours}

## 付费服务信息
- 评估服务价格: ¥${strategy.paidServices.assessmentPrice}
- 服务说明: ${strategy.paidServices.description}

================================================================================
`;

    return injectedContent;
  }

  /**
   * 构建设备上下文信息（用于新用户破冰）
   */
  private buildDeviceContext(context: ConversationContext, isFirstMessage: boolean): string {
    if (!isFirstMessage || !context.deviceInfo) {
      return '';
    }

    const parts: string[] = ['## 用户设备信息（可用于破冰参考）'];

    if (context.deviceInfo.ip) {
      // 可以根据IP判断地区
      parts.push(`- IP地址: ${context.deviceInfo.ip} (可用于判断用户所在地区)`);
    }

    if (context.deviceInfo.userAgent) {
      const ua = context.deviceInfo.userAgent;
      if (ua.includes('Mobile')) {
        parts.push('- 设备类型: 移动设备');
      } else {
        parts.push('- 设备类型: 电脑');
      }
    }

    if (context.deviceInfo.fingerprint) {
      parts.push(`- 设备指纹: ${context.deviceInfo.fingerprint.slice(0, 8)}...`);
    }

    parts.push('');
    parts.push('提示: 可以根据设备信息进行自然的寒暄，如"在手机上咨询呢"等');

    return parts.join('\n');
  }

  /**
   * 根据意图和阶段计算max_tokens
   */
  private calculateMaxTokens(intent: IntentResult, state: ConsultingState): number {
    const stage = this.strategyEngine.getCurrentStage(state);
    const baseLength = stage.suggestedResponseLength;

    // 中文约 1.8 tokens/字符
    const tokensPerChar = 1.8;
    const baseTokens = Math.round(baseLength * tokensPerChar);

    // 根据阶段调整
    switch (state.currentStageId) {
      case StageId.GREETING:
        return Math.min(400, baseTokens);
      case StageId.NEEDS_DISCOVERY:
        return Math.min(500, baseTokens);
      case StageId.INFO_COLLECTION:
        return Math.min(450, baseTokens);
      case StageId.ASSESSMENT:
        return Math.min(800, baseTokens);
      case StageId.RECOMMENDATION:
        return Math.min(1000, baseTokens);
      case StageId.OBJECTION_HANDLING:
        return Math.min(600, baseTokens);
      case StageId.CONVERSION:
        return Math.min(600, baseTokens);
      case StageId.HANDOFF:
        return Math.min(500, baseTokens);
      default:
        return 800;
    }
  }

  /**
   * 获取已积累的经验
   */
  private async getAccumulatedExperience(query: string): Promise<string> {
    try {
      const experiences = await this.knowledgeClient.searchExperiences({
        query,
        activeOnly: true,
        limit: 5,
      });

      if (experiences.length === 0) {
        return '暂无';
      }

      return experiences
        .map((exp, index) => `${index + 1}. [${exp.experienceType}] ${exp.content}`)
        .join('\n');
    } catch (error) {
      console.error('[ClaudeAgentV2] Failed to fetch experiences:', error);
      return '暂无';
    }
  }

  /**
   * 构建多模态内容
   */
  private async buildMultimodalContent(
    text: string,
    attachments?: FileAttachment[],
  ): Promise<Anthropic.ContentBlockParam[]> {
    const content: Anthropic.ContentBlockParam[] = [];

    if (attachments && attachments.length > 0) {
      for (const attachment of attachments) {
        if (attachment.type === 'image' && attachment.downloadUrl) {
          try {
            const response = await fetch(attachment.downloadUrl);
            if (response.ok) {
              const buffer = await response.arrayBuffer();
              const base64Data = Buffer.from(buffer).toString('base64');
              const mediaType = attachment.mimeType as 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp';

              content.push({
                type: 'image',
                source: {
                  type: 'base64',
                  media_type: mediaType,
                  data: base64Data,
                },
              });
            }
          } catch (error) {
            console.error(`Failed to fetch image ${attachment.originalName}:`, error);
          }
        } else if (attachment.type === 'document') {
          content.push({
            type: 'text',
            text: `[Attached document: ${attachment.originalName}]`,
          });
        }
      }
    }

    if (text) {
      content.push({ type: 'text', text });
    }

    return content;
  }

  /**
   * 更新系统提示配置
   */
  updateSystemPromptConfig(config: Partial<SystemPromptConfig>) {
    this.systemPromptConfig = {
      ...this.systemPromptConfig,
      ...config,
    };
  }
}
