#!/usr/bin/env node

/**
 * Verification script for builder message sending to OpenCode
 * This script validates that all components for message sending are correct
 */

const fs = require('fs');
const path = require('path');

console.log('╔══════════════════════════════════════════════════════════════╗');
console.log('║  Builder → OpenCode Message Flow Verification               ║');
console.log('╚══════════════════════════════════════════════════════════════╝\n');

const rootDir = path.join(__dirname, '..');
let allChecks = true;
let checkCount = 0;
let passCount = 0;

function check(condition, description) {
  checkCount++;
  if (condition) {
    passCount++;
    console.log(`✓ ${description}`);
    return true;
  } else {
    allChecks = false;
    console.log(`✗ ${description}`);
    return false;
  }
}

// Load files
console.log('Loading files...\n');
const builderJsPath = path.join(rootDir, 'chat/public/builder.js');
const serverJsPath = path.join(rootDir, 'chat/server.js');
const builderHtmlPath = path.join(rootDir, 'chat/public/builder.html');

let builderJs, serverJs, builderHtml;

try {
  builderJs = fs.readFileSync(builderJsPath, 'utf8');
  check(true, 'Loaded builder.js');
} catch (e) {
  check(false, `Failed to load builder.js: ${e.message}`);
  process.exit(1);
}

try {
  serverJs = fs.readFileSync(serverJsPath, 'utf8');
  check(true, 'Loaded server.js');
} catch (e) {
  check(false, `Failed to load server.js: ${e.message}`);
  process.exit(1);
}

try {
  builderHtml = fs.readFileSync(builderHtmlPath, 'utf8');
  check(true, 'Loaded builder.html');
} catch (e) {
  check(false, `Failed to load builder.html: ${e.message}`);
  process.exit(1);
}

console.log('\n--- File Syntax Validation ---\n');

// Check syntax of JS files
try {
  new (require('vm').Script)(builderJs, { filename: 'builder.js' });
  check(true, 'builder.js syntax is valid');
} catch (e) {
  check(false, `builder.js has syntax error: ${e.message}`);
}

try {
  new (require('vm').Script)(serverJs, { filename: 'server.js' });
  check(true, 'server.js syntax is valid');
} catch (e) {
  check(false, `server.js has syntax error: ${e.message}`);
}

console.log('\n--- Builder.js Message Sending ---\n');

// Check executeBuild function
check(
  builderJs.includes('async function executeBuild(planContent)'),
  'executeBuild function exists'
);

check(
  builderJs.includes('await api(`/api/sessions/${state.currentSessionId}/messages`'),
  'executeBuild sends to correct API endpoint'
);

check(
  builderJs.includes("cli: 'opencode'"),
  'executeBuild sets cli to "opencode"'
);

check(
  builderJs.includes('isProceedWithBuild: true'),
  'executeBuild sets isProceedWithBuild flag'
);

check(
  builderJs.includes('planContent: planContent'),
  'executeBuild includes planContent in payload'
);

check(
  builderJs.includes('streamMessage(state.currentSessionId, response.message.id)'),
  'executeBuild starts streaming after message creation'
);

// Check redoProceedWithBuild function
check(
  builderJs.includes('async function redoProceedWithBuild(planContent, model)'),
  'redoProceedWithBuild function exists'
);

// Check sendMessage function
check(
  builderJs.includes('async function sendMessage()'),
  'sendMessage function exists'
);

check(
  builderJs.includes('await api(`/api/sessions/${state.currentSessionId}/messages`'),
  'sendMessage sends to correct API endpoint'
);

console.log('\n--- Server.js Message Handling ---\n');

// Check route matching
check(
  serverJs.includes('const messageMatch = pathname.match') && 
  serverJs.includes('api') && serverJs.includes('sessions') && serverJs.includes('messages'),
  'Server has message route matcher'
);

check(
  serverJs.includes('return handleNewMessage(req, res, messageMatch[1], userId)'),
  'Server routes to handleNewMessage'
);

// Check handleNewMessage function
check(
  serverJs.includes('async function handleNewMessage(req, res, sessionId, userId)'),
  'handleNewMessage function exists'
);

check(
  serverJs.includes('const content = sanitizeMessage(body.content'),
  'handleNewMessage extracts and sanitizes content'
);

check(
  serverJs.includes('const cli = normalizeCli(body.cli || session.cli)'),
  'handleNewMessage extracts CLI'
);

check(
  serverJs.includes('session.messages.push(message)'),
  'handleNewMessage adds message to session'
);

check(
  serverJs.includes('queueMessage(sessionId, message)'),
  'handleNewMessage queues message'
);

console.log('\n--- Message Processing ---\n');

// Check processMessage function
check(
  serverJs.includes('async function processMessage(sessionId, message)'),
  'processMessage function exists'
);

check(
  serverJs.includes('const opencodeResult = await sendToOpencodeWithFallback'),
  'processMessage calls sendToOpencodeWithFallback'
);

// Check sendToOpencodeWithFallback function
check(
  serverJs.includes('async function sendToOpencodeWithFallback'),
  'sendToOpencodeWithFallback function exists'
);

check(
  serverJs.includes('const result = await sendToOpencode'),
  'sendToOpencodeWithFallback calls sendToOpencode'
);

console.log('\n--- OpenCode Integration ---\n');

// Check sendToOpencode function
check(
  serverJs.includes('async function sendToOpencode({ session, model, content, message, cli, streamCallback, opencodeSessionId })'),
  'sendToOpencode function exists'
);

check(
  serverJs.includes('const clean = sanitizeMessage(content)'),
  'sendToOpencode sanitizes content'
);

check(
  serverJs.includes("const args = ['run', '--model', resolvedModel]"),
  'sendToOpencode prepares CLI arguments'
);

check(
  serverJs.includes('args.push(clean)'),
  'sendToOpencode adds content as argument'
);

check(
  serverJs.includes('const { stdout, stderr } = await runCommand(cliCommand, args'),
  'sendToOpencode executes OpenCode CLI'
);

console.log('\n--- Streaming Support ---\n');

// Check streaming functionality
check(
  builderJs.includes('function streamMessage(sessionId, messageId)'),
  'streamMessage function exists in builder'
);

check(
  builderJs.includes('const url = `/api/sessions/${sessionId}/messages/${messageId}/stream`'),
  'streamMessage connects to correct endpoint'
);

check(
  builderJs.includes('const eventSource = new EventSource(url)'),
  'streamMessage uses EventSource for SSE'
);

check(
  serverJs.includes('async function handleMessageStream(req, res, sessionId, messageId, userId)'),
  'handleMessageStream function exists in server'
);

check(
  serverJs.includes("'Content-Type': 'text/event-stream'"),
  'Server sets correct content type for SSE'
);

console.log('\n--- Summary ---\n');

const percentage = ((passCount / checkCount) * 100).toFixed(1);
console.log(`Checks passed: ${passCount}/${checkCount} (${percentage}%)`);

if (allChecks) {
  console.log('\n✅ ALL CHECKS PASSED');
  console.log('\nThe builder message sending flow is correctly implemented.');
  console.log('All files are valid and components are properly connected.');
  console.log('Messages should successfully flow: Builder → Server → OpenCode\n');
  
  console.log('If messages are not being sent, check:');
  console.log('  1. OpenCode CLI is installed and accessible');
  console.log('  2. Server is running and accessible');
  console.log('  3. User has a valid session');
  console.log('  4. Model is properly configured');
  console.log('  5. Browser console for runtime errors');
  console.log('  6. Server logs for processing errors');
  process.exit(0);
} else {
  console.log('\n❌ SOME CHECKS FAILED');
  console.log('\nReview the failed checks above to identify issues.\n');
  process.exit(1);
}
