import assert from 'node:assert/strict'
import path from 'node:path'
import process from 'node:process'

import { Client } from '@modelcontextprotocol/sdk/client/index.js'
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'

const transport = new StdioClientTransport({
  command: process.execPath,
  args: [path.join(process.cwd(), 'mcp-server.mjs')],
  cwd: process.cwd(),
  stderr: 'pipe'
})

let stderrOutput = ''
transport.stderr?.setEncoding('utf8')
transport.stderr?.on('data', (chunk) => {
  stderrOutput += chunk
})

const client = new Client({
  name: 'notenextra-mcp-test',
  version: '1.0.0'
})

async function main() {
  await client.connect(transport)

  const toolListResponse = await client.listTools()
  const toolNames = toolListResponse.tools.map((tool) => tool.name).sort()
  assert.deepEqual(toolNames, ['list_notes', 'read_note', 'search_notes'])

  const listNotesResponse = await client.callTool({
    name: 'list_notes',
    arguments: {
      course: 'CSE442T'
    }
  })
  const listedNotes = listNotesResponse.content[0].text
  assert.match(listedNotes, /CSE442T\/CSE442T_L1/, 'list_notes should include CSE442T lecture notes')

  const readNoteResponse = await client.callTool({
    name: 'read_note',
    arguments: {
      noteId: 'about'
    }
  })
  const aboutText = readNoteResponse.content[0].text
  assert.match(aboutText, /# about/i)
  assert.match(aboutText, /This is a static server for me to share my notes/i)

  const searchResponse = await client.callTool({
    name: 'search_notes',
    arguments: {
      query: "Kerckhoffs' principle",
      limit: 3
    }
  })
  const searchText = searchResponse.content[0].text
  assert.match(searchText, /CSE442T\/CSE442T_L1/, 'search_notes should find the cryptography lecture')
  assert.match(searchText, /Kerckhoffs/i)
}

try {
  await main()
  process.stdout.write('MCP server test passed.\n')
} catch (error) {
  const suffix = stderrOutput ? `\nServer stderr:\n${stderrOutput}` : ''
  process.stderr.write(`${error.stack || error}${suffix}\n`)
  process.exitCode = 1
} finally {
  await client.close().catch(() => {})
  await transport.close().catch(() => {})
}
