import OpenAI from 'openai';
import type { AiProvider, PingRequest, PingResponse, ToolCallRequest, ToolCallResponse } from './provider.interface';

/**
 * OpenAI 格式提供商（兼容 OpenAI Chat Completions 风格的中转站）
 */
export class OpenAIProvider implements AiProvider {
  readonly format = 'openai' as const;
  private client: OpenAI;

  constructor(apiKey: string, baseURL: string) {
    this.client = new OpenAI({
      apiKey,
      baseURL,
    });
  }

  async callTool(req: ToolCallRequest): Promise<ToolCallResponse> {
    const response = await this.client.chat.completions.create({
      model: req.model,
      max_tokens: req.maxTokens,
      messages: [
        { role: 'system', content: req.systemPrompt },
        { role: 'user', content: req.userPrompt },
      ],
      tools: [
        {
          type: 'function',
          function: {
            name: req.tool.name,
            description: req.tool.description,
            parameters: req.tool.inputSchema,
          },
        },
      ],
      tool_choice: req.forceTool
        ? { type: 'function', function: { name: req.tool.name } }
        : 'auto',
    });

    const choice = response.choices[0];
    if (!choice?.message?.tool_calls?.length) {
      throw new Error('OpenAI 未通过 tool_calls 返回结果');
    }

    const tc = choice.message.tool_calls[0];
    if (tc.type !== 'function') {
      throw new Error('OpenAI 返回的 tool_call 类型非 function');
    }

    let parsed: Record<string, any>;
    try {
      parsed = JSON.parse(tc.function.arguments || '{}');
    } catch (e) {
      throw new Error(`OpenAI tool_call arguments 不是合法 JSON: ${(e as Error).message}`);
    }

    return {
      toolName: tc.function.name,
      toolInput: parsed,
      inputTokens: response.usage?.prompt_tokens ?? 0,
      outputTokens: response.usage?.completion_tokens ?? 0,
      rawModel: response.model,
    };
  }

  async ping(req: PingRequest): Promise<PingResponse> {
    const resp = await this.client.chat.completions.create({
      model: req.model,
      max_tokens: 16,
      messages: [{ role: 'user', content: 'ping' }],
    });
    return {
      ok: true,
      inputTokens: resp.usage?.prompt_tokens ?? 0,
      outputTokens: resp.usage?.completion_tokens ?? 0,
    };
  }
}
