/**
 * OpenRouter Chat Completion Client
 *
 * Provides chat completion functionality using OpenRouter API
 * with support for tool/function calling.
 *
 * Used primarily for call log analytics with Google Gemini 2.5 Flash.
 */

// OpenRouter API configuration
const OPENROUTER_API_URL = 'https://openrouter.ai/api/v1/chat/completions';
const DEFAULT_MODEL = 'google/gemini-2.5-flash';

// Type definitions
export interface ChatMessage {
  role: 'system' | 'user' | 'assistant' | 'tool';
  content: string | null;
  tool_calls?: ToolCall[];
  tool_call_id?: string;
  name?: string;
}

export interface ToolCall {
  id: string;
  type: 'function';
  function: {
    name: string;
    arguments: string;
  };
}

export interface Tool {
  type: 'function';
  function: {
    name: string;
    description: string;
    parameters: {
      type: 'object';
      properties: Record<string, {
        type: string;
        description?: string;
        enum?: string[];
      }>;
      required?: string[];
    };
  };
}

export interface ChatCompletionOptions {
  model?: string;
  messages: ChatMessage[];
  tools?: Tool[];
  tool_choice?: 'auto' | 'none' | { type: 'function'; function: { name: string } };
  response_format?: { type: 'json_object' | 'text' };
  temperature?: number;
  max_tokens?: number;
}

export interface ChatCompletionResponse {
  id: string;
  choices: Array<{
    index: number;
    message: {
      role: 'assistant';
      content: string | null;
      tool_calls?: ToolCall[];
    };
    finish_reason: 'stop' | 'tool_calls' | 'length' | 'content_filter';
  }>;
  usage?: {
    prompt_tokens: number;
    completion_tokens: number;
    total_tokens: number;
  };
}

export interface ChatCompletionError {
  error: {
    message: string;
    type: string;
    code?: string;
  };
}

/**
 * Make a chat completion request to OpenRouter API
 */
export async function chatCompletion(
  options: ChatCompletionOptions
): Promise<ChatCompletionResponse> {
  const OPENROUTER_API_KEY = Deno.env.get('OPENROUTER_API_KEY');

  if (!OPENROUTER_API_KEY) {
    throw new Error('OPENROUTER_API_KEY environment variable not set');
  }

  const {
    model = DEFAULT_MODEL,
    messages,
    tools,
    tool_choice,
    response_format,
    temperature = 0.3,
    max_tokens = 4096,
  } = options;

  const requestBody: Record<string, unknown> = {
    model,
    messages,
    temperature,
    max_tokens,
  };

  // Add optional parameters
  if (tools && tools.length > 0) {
    requestBody.tools = tools;
    requestBody.tool_choice = tool_choice || 'auto';
  }

  if (response_format) {
    requestBody.response_format = response_format;
  }

  console.log(`[OpenRouter] Making chat completion request with model: ${model}`);
  console.log(`[OpenRouter] Messages count: ${messages.length}, Tools count: ${tools?.length || 0}`);

  const response = await fetch(OPENROUTER_API_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${OPENROUTER_API_KEY}`,
      'HTTP-Referer': 'https://shopcall.ai',
      'X-Title': 'ShopCall.ai Call Analytics',
    },
    body: JSON.stringify(requestBody),
  });

  if (!response.ok) {
    const errorText = await response.text();
    console.error(`[OpenRouter] API error (${response.status}):`, errorText);

    let errorData: ChatCompletionError;
    try {
      errorData = JSON.parse(errorText);
    } catch {
      throw new Error(`OpenRouter API error: ${response.status} - ${errorText}`);
    }

    throw new Error(`OpenRouter API error: ${errorData.error?.message || response.statusText}`);
  }

  const data = await response.json() as ChatCompletionResponse;

  console.log(`[OpenRouter] Response received. Finish reason: ${data.choices?.[0]?.finish_reason}`);
  if (data.usage) {
    console.log(`[OpenRouter] Token usage - Prompt: ${data.usage.prompt_tokens}, Completion: ${data.usage.completion_tokens}, Total: ${data.usage.total_tokens}`);
  }

  return data;
}

/**
 * Helper to extract text content from a chat completion response
 */
export function getMessageContent(response: ChatCompletionResponse): string | null {
  return response.choices?.[0]?.message?.content ?? null;
}

/**
 * Helper to check if the response has tool calls
 */
export function hasToolCalls(response: ChatCompletionResponse): boolean {
  return (response.choices?.[0]?.message?.tool_calls?.length ?? 0) > 0;
}

/**
 * Helper to get tool calls from a response
 */
export function getToolCalls(response: ChatCompletionResponse): ToolCall[] {
  return response.choices?.[0]?.message?.tool_calls ?? [];
}

/**
 * Helper to parse JSON content from response, handling potential markdown code blocks
 */
export function parseJsonContent<T>(content: string | null): T | null {
  if (!content) return null;

  // Try to extract JSON from markdown code blocks if present
  let jsonString = content.trim();

  // Handle ```json ... ``` blocks
  const jsonBlockMatch = jsonString.match(/```(?:json)?\s*([\s\S]*?)```/);
  if (jsonBlockMatch) {
    jsonString = jsonBlockMatch[1].trim();
  }

  try {
    return JSON.parse(jsonString) as T;
  } catch (error) {
    console.error('[OpenRouter] Failed to parse JSON content:', error);
    console.error('[OpenRouter] Raw content:', content.substring(0, 500));
    return null;
  }
}

/**
 * Create a tool result message for continuing the conversation
 */
export function createToolResultMessage(toolCallId: string, result: unknown): ChatMessage {
  return {
    role: 'tool',
    tool_call_id: toolCallId,
    content: typeof result === 'string' ? result : JSON.stringify(result),
  };
}

/**
 * Run a conversation with tool calls until completion
 *
 * @param options Initial chat options
 * @param toolExecutor Function that executes tool calls and returns results
 * @param maxIterations Maximum number of tool call iterations (prevents infinite loops)
 */
export async function runConversationWithTools(
  options: ChatCompletionOptions,
  toolExecutor: (toolCall: ToolCall) => Promise<unknown>,
  maxIterations: number = 10
): Promise<ChatCompletionResponse> {
  const messages = [...options.messages];
  let iteration = 0;
  let lastResponse: ChatCompletionResponse;

  while (iteration < maxIterations) {
    console.log(`[OpenRouter] Conversation iteration ${iteration + 1}`);

    lastResponse = await chatCompletion({
      ...options,
      messages,
    });

    // Check if we have tool calls to process
    if (!hasToolCalls(lastResponse)) {
      console.log('[OpenRouter] No more tool calls, conversation complete');
      return lastResponse;
    }

    const toolCalls = getToolCalls(lastResponse);
    console.log(`[OpenRouter] Processing ${toolCalls.length} tool call(s)`);

    // Add assistant message with tool calls
    messages.push({
      role: 'assistant',
      content: null,
      tool_calls: toolCalls,
    });

    // Execute each tool call and add results
    for (const toolCall of toolCalls) {
      console.log(`[OpenRouter] Executing tool: ${toolCall.function.name}`);

      try {
        const result = await toolExecutor(toolCall);
        messages.push(createToolResultMessage(toolCall.id, result));
      } catch (error) {
        console.error(`[OpenRouter] Tool execution error for ${toolCall.function.name}:`, error);
        messages.push(createToolResultMessage(toolCall.id, {
          error: true,
          message: error instanceof Error ? error.message : 'Unknown error',
        }));
      }
    }

    iteration++;
  }

  console.warn(`[OpenRouter] Max iterations (${maxIterations}) reached, forcing completion`);

  // If we hit max iterations, make one final call without tools to get a response
  return await chatCompletion({
    ...options,
    messages,
    tools: undefined,
    tool_choice: undefined,
  });
}
