/**
 * Tool registry: Notion read/write + code repo read/write
 * 
 * Defines tools the model can call during conversation.
 * Tool call format in model output:
 * <<tool:tool_name param1="value" param2="value">>
 * 
 * Tools connect to MCP endpoints via connector-proxy.
 */
'use strict';

const https = require('https');
const http = require('http');

// MCP proxy configuration
const MCP_PROXY = process.env.MCP_PROXY_URL || 'http://localhost:3010';

/**
 * Parse a tool call from model output
 * Format: <<tool:tool_name param1="value" param2="value">>
 */
function parseToolCall(text) {
  if (!text) return null;
  const match = text.match(/<<tool:(\w+)\s+([^>]+)>>/);
  if (!match) return null;

  const toolName = match[1];
  const argsStr = match[2];
  const args = {};

  // Parse key="value" pairs
  const argRegex = /(\w+)="([^"]*)"/g;
  let argMatch;
  while ((argMatch = argRegex.exec(argsStr)) !== null) {
    args[argMatch[1]] = argMatch[2];
  }

  return { tool: toolName, args };
}

/**
 * Execute a parsed tool call
 */
async function executeToolCall(toolCall) {
  if (!toolCall || !toolCall.tool) {
    throw new Error('Invalid tool call');
  }

  switch (toolCall.tool) {
    case 'read_notion':
      return await readNotion(toolCall.args);
    case 'write_notion':
      return await writeNotion(toolCall.args);
    case 'read_repo':
      return await readRepo(toolCall.args);
    case 'write_repo':
      return await writeRepo(toolCall.args);
    case 'search_repo':
      return await searchRepo(toolCall.args);
    default:
      throw new Error('Unknown tool: ' + toolCall.tool);
  }
}

/**
 * List available tools (for model guidance)
 */
function listTools() {
  return [
    {
      name: 'read_notion',
      description: 'Read content from a Notion page',
      params: { page_id: 'string - The Notion page ID to read' }
    },
    {
      name: 'write_notion',
      description: 'Append content to a Notion page',
      params: { page_id: 'string - The Notion page ID', content: 'string - Content to append' }
    },
    {
      name: 'read_repo',
      description: 'Read a file from the code repository',
      params: { path: 'string - File path in repo' }
    },
    {
      name: 'write_repo',
      description: 'Write a file to the code repository',
      params: { path: 'string - File path', content: 'string - File content' }
    },
    {
      name: 'search_repo',
      description: 'Search code in the repository',
      params: { query: 'string - Search keyword' }
    }
  ];
}

/**
 * Build a tool usage guide string for the model
 */
function buildToolGuide() {
  const tools = listTools();
  let guide = 'Available tools (use <<tool:name key="value">> to call):\n';
  for (const t of tools) {
    guide += `- ${t.name}: ${t.description}\n`;
    for (const [k, v] of Object.entries(t.params)) {
      guide += `  ${k}: ${v}\n`;
    }
  }
  return guide;
}

// ─── Tool Implementations ───

function mcpRequest(method, path, body) {
  const url = new URL(MCP_PROXY);
  const transport = url.protocol === 'https:' ? https : http;

  return new Promise((resolve, reject) => {
    const options = {
      hostname: url.hostname,
      port: url.port || 80,
      path: path,
      method: method,
      headers: { 'Content-Type': 'application/json' }
    };

    const req = transport.request(options, (res) => {
      let data = '';
      res.on('data', chunk => data += chunk);
      res.on('end', () => {
        try { resolve(JSON.parse(data)); }
        catch (e) { resolve({ raw: data }); }
      });
    });

    req.on('error', reject);
    if (body) req.write(JSON.stringify(body));
    req.end();
  });
}

async function readNotion(args) {
  const pageId = args.page_id || args.pageId;
  if (!pageId) throw new Error('read_notion requires page_id');
  // Use the connector-proxy MCP endpoint for Notion
  return await mcpRequest('POST', '/api/mcp/notion/read', { page_id: pageId });
}

async function writeNotion(args) {
  const pageId = args.page_id || args.pageId;
  const content = args.content;
  if (!pageId || !content) throw new Error('write_notion requires page_id and content');
  return await mcpRequest('POST', '/api/mcp/notion/append', { page_id: pageId, content });
}

async function readRepo(args) {
  const path = args.path;
  if (!path) throw new Error('read_repo requires path');
  return await mcpRequest('POST', '/api/mcp/repo/read', { path });
}

async function writeRepo(args) {
  const path = args.path;
  const content = args.content;
  if (!path || !content) throw new Error('write_repo requires path and content');
  return await mcpRequest('POST', '/api/mcp/repo/write', { path, content });
}

async function searchRepo(args) {
  const query = args.query;
  if (!query) throw new Error('search_repo requires query');
  return await mcpRequest('POST', '/api/mcp/repo/search', { query });
}

module.exports = {
  parseToolCall,
  executeToolCall,
  listTools,
  buildToolGuide
};
