import Anthropic from '@anthropic-ai/sdk';
import { LLMProvider, LLMMessage, LLMResponse, LLMProviderConfig, ToolCall, LLMChatCallbacks } from '../plugin_entry.js';
import { AnyAgentTool } from '../../tools/common.js';
import { buildAnthropicThinkingParams } from '../../runtime/thinking.js';
import { logProviderResponse } from './logging.js';

export class AnthropicProvider implements LLMProvider {
  id = 'anthropic';
  name = 'Anthropic Claude';

  async chat(
    messages: LLMMessage[],
    tools: AnyAgentTool[],
    config: LLMProviderConfig,
    _callbacks?: LLMChatCallbacks
  ): Promise<LLMResponse> {
    const client = new Anthropic({ apiKey: config.apiKey, baseURL: config.baseUrl });

    const systemMsg = messages.find(m => m.role === 'system');
    const chatMessages = messages
      .filter(m => m.role !== 'system')
      .map(m => this.toAnthropicMessage(m));

    const anthropicTools = tools.map(t => ({
      name: t.name,
      description: t.description,
      input_schema: t.parameters as Anthropic.Tool.InputSchema,
    }));

    // 构建基础请求参数
    const createParams: Anthropic.MessageCreateParamsNonStreaming = {
      model: config.model,
      max_tokens: config.maxTokens ?? 4096,
      system: systemMsg?.content ?? '',
      messages: chatMessages,
      tools: anthropicTools.length > 0 ? anthropicTools : undefined,
      temperature: config.temperature,
    };

    // 注入 thinking 参数（如果启用了思考模式）
    const thinkParams = buildAnthropicThinkingParams(config.model, config.thinkLevel || 'off');
    if (thinkParams) {
      (createParams as any).thinking = thinkParams.thinking;
      // thinking 模式要求 temperature 固定为 1
      if (thinkParams.temperature !== undefined) {
        createParams.temperature = thinkParams.temperature;
      }
      // 确保 max_tokens 满足 thinking 模式的最低要求
      if (thinkParams.maxTokensAdjust) {
        createParams.max_tokens = Math.max(createParams.max_tokens, thinkParams.maxTokensAdjust);
      }
    }

    const response = await client.messages.create(createParams);

    return this.parseResponse(response, config);
  }

  private toAnthropicMessage(msg: LLMMessage): Anthropic.MessageParam {
    if (msg.role === 'assistant' && msg.toolCalls?.length) {
      return {
        role: 'assistant',
        content: [
          ...(msg.content ? [{ type: 'text' as const, text: msg.content }] : []),
          ...msg.toolCalls.map(tc => ({
            type: 'tool_use' as const,
            id: tc.id,
            name: tc.name,
            input: JSON.parse(tc.arguments),
          })),
        ],
      };
    }
    if (msg.role === 'tool') {
      return {
        role: 'user',
        content: [{ type: 'tool_result' as const, tool_use_id: msg.toolCallId!, content: msg.content }],
      };
    }
    return { role: msg.role as 'user' | 'assistant', content: msg.content };
  }

  private parseResponse(response: Anthropic.Message, config: LLMProviderConfig): LLMResponse {
    let content = '';
    let thinking = '';
    const toolCalls: ToolCall[] = [];

    for (const block of response.content) {
      if (block.type === 'text') content += block.text;
      if (block.type === 'thinking') thinking += (block as any).thinking;
      if (block.type === 'tool_use') {
        toolCalls.push({ id: block.id, name: block.name, arguments: JSON.stringify(block.input) });
      }
    }

    logProviderResponse({
      providerId: this.id,
      providerName: this.name,
      channelSupplier: config.channelSupplier,
      channelId: config.channelId,
      channelName: config.channelName,
      model: config.model,
      baseUrl: config.baseUrl,
      thinkLevel: config.thinkLevel,
      rawResponse: {
        id: response.id,
        model: response.model,
        stop_reason: response.stop_reason,
        usage: response.usage,
        content: response.content,
      },
      parsed: {
        content,
        thinking,
        thinkSource: thinking ? 'content_block_thinking' : undefined,
        toolCallCount: toolCalls.length,
        stopReason: response.stop_reason ?? undefined,
      },
    });

    return {
      content,
      thinking: thinking || undefined,
      toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
      usage: { inputTokens: response.usage.input_tokens, outputTokens: response.usage.output_tokens },
      stopReason: response.stop_reason === 'tool_use' ? 'tool_use' : 'end_turn',
    };
  }
}
