#!/usr/bin/env node --experimental-strip-types
import { spawn } from '@socketsecurity/lib-stable/process/spawn/child'
import path from 'node:path'
import readline from 'node:readline'
import { getDefaultLogger } from '@socketsecurity/lib/logger/default'

const logger = getDefaultLogger()

// Simple JSON-RPC client for testing MCP server
export class SimpleJSONRPCClient {
  private spawned: ReturnType<typeof spawn>
  private rl: readline.Interface
  private requestId = 1
  private pendingRequests = new Map()

  constructor(
    command: string,
    args: string[] = [],
    env: Record<string, string> = {},
  ) {
    this.spawned = spawn(command, args, {
      stdio: ['pipe', 'pipe', 'pipe'],
      env: { ...process.env, ...env },
    })

    this.rl = readline.createInterface({
      input: this.spawned.process.stdout!,
      crlfDelay: Infinity,
    })

    this.rl.on('line', line => {
      try {
        const response = JSON.parse(line)
        if (response.id && this.pendingRequests.has(response.id)) {
          const { resolve, reject } = this.pendingRequests.get(response.id)
          this.pendingRequests.delete(response.id)

          if (response.error) {
            reject(response.error)
          } else {
            resolve(response.result)
          }
        } else if (response.method) {
          logger.log('Notification:', response)
        }
      } catch (e) {
        logger.error('Failed to parse response:', line)
      }
    })

    this.spawned.process.stderr!.on('data', (data: Buffer) => {
      logger.error('Server stderr:', data.toString())
    })
  }

  async sendRequest(method: string, params: Record<string, unknown> = {}) {
    const id = this.requestId++
    const request = {
      jsonrpc: '2.0',
      id,
      method,
      params,
    }

    return new Promise((resolve, reject) => {
      this.pendingRequests.set(id, { resolve, reject })
      this.spawned.stdin?.write(JSON.stringify(request) + '\n')
    })
  }

  close() {
    this.rl.close()
    this.spawned.process.kill()
  }
}

async function main() {
  // socket-api-token-getter: allow direct-env — mock client / dev tool, not the runtime auth path.
  const apiKey = process.env['SOCKET_API_TOKEN']
  if (!apiKey) {
    logger.error('Error: SOCKET_API_KEY environment variable is required')
    process.exit(1)
  }

  logger.info('Starting MCP server debug client…')

  const serverPath = path.join(import.meta.dirname, '..', 'index.ts')
  logger.info(`Using server script: ${serverPath}`)

  const client = new SimpleJSONRPCClient(
    'node',
    ['--experimental-strip-types', serverPath],
    {
      SOCKET_API_KEY: apiKey,
    },
  )

  try {
    // Initialize the connection
    logger.error('')
    logger.info('1. Initializing connection…')
    const initResult = await client.sendRequest('initialize', {
      protocolVersion: '0.1.0',
      capabilities: {},
      clientInfo: {
        name: 'debug-client',
        version: '1.0.0',
      },
    })
    logger.info('Initialize response:', JSON.stringify(initResult, null, 2))

    // List available tools
    logger.error('')
    logger.info('2. Listing available tools…')
    const toolsResult = await client.sendRequest('tools/list', {})
    logger.info('Available tools:', JSON.stringify(toolsResult, null, 2))

    // Call the depscore tool
    logger.error('')
    logger.info('3. Calling depscore tool…')
    const depscoreResult = await client.sendRequest('tools/call', {
      name: 'depscore',
      arguments: {
        packages: [
          { depname: 'express', ecosystem: 'npm', version: '5.0.1' },
          { depname: 'lodash', ecosystem: 'npm', version: '4.17.21' },
          { depname: 'react', ecosystem: 'npm', version: '18.2.0' },
          { depname: 'flask', ecosystem: 'pypi', version: '2.3.2' },
          { depname: 'unknown-package', ecosystem: 'npm', version: 'unknown' },
        ],
      },
    })
    logger.info('Depscore result:', JSON.stringify(depscoreResult, null, 2))

    // Test with minimal input
    logger.error('')
    logger.info('4. Testing with minimal input (default to npm)...')
    const minimalResult = await client.sendRequest('tools/call', {
      name: 'depscore',
      arguments: {
        packages: [{ depname: 'axios' }, { depname: 'typescript' }],
      },
    })
    logger.info('Minimal input result:', JSON.stringify(minimalResult, null, 2))

    // Test error handling
    logger.error('')
    logger.info('5. Testing error handling (empty packages)...')
    try {
      await client.sendRequest('tools/call', {
        name: 'depscore',
        arguments: {
          packages: [],
        },
      })
    } catch (error) {
      logger.info('Expected error:', error)
    }

    logger.error('')
    logger.info('Debug session complete!')
  } catch (error) {
    logger.error('Client error:', error)
  } finally {
    client.close()
  }
}

main().catch(e => logger.error(e))
