#!/usr/bin/env node
// chatgpt-send.mjs — Send a prompt to ChatGPT via the user's running Brave browser
// Connects via Chrome DevTools Protocol to an already-authenticated session.
//
// Usage: node chatgpt-send.mjs <prompt-file> <output-file> [--timeout <seconds>]
//
// Requires: Brave running with --remote-debugging-port=9222

import puppeteer from 'puppeteer-core';
import { readFileSync, writeFileSync } from 'fs';

const CDP_URL = `http://127.0.0.1:${process.env.CHATGPT_CDP_PORT || '9222'}`;
const DEFAULT_TIMEOUT_SEC = 600; // 10 minutes for long responses

function parseArgs() {
  const args = process.argv.slice(2);
  let promptFile = null;
  let outputFile = null;
  let timeoutSec = DEFAULT_TIMEOUT_SEC;

  for (let i = 0; i < args.length; i++) {
    if (args[i] === '--timeout' && args[i + 1]) {
      timeoutSec = parseInt(args[i + 1], 10);
      i++;
    } else if (!promptFile) {
      promptFile = args[i];
    } else if (!outputFile) {
      outputFile = args[i];
    }
  }

  if (!promptFile || !outputFile) {
    console.error('Usage: node chatgpt-send.mjs <prompt-file> <output-file> [--timeout <seconds>]');
    process.exit(2);
  }

  return { promptFile, outputFile, timeoutSec };
}

async function waitForSelector(page, selector, timeout) {
  return page.waitForSelector(selector, { timeout });
}

async function main() {
  const { promptFile, outputFile, timeoutSec } = parseArgs();
  const prompt = readFileSync(promptFile, 'utf-8').trim();
  const timeoutMs = timeoutSec * 1000;

  // Connect to running Brave
  let browser;
  try {
    browser = await puppeteer.connect({ browserURL: CDP_URL });
  } catch (err) {
    console.error(`Cannot connect to Brave at ${CDP_URL}`);
    console.error('Make sure Brave is running with: --remote-debugging-port=9222');
    console.error('');
    console.error('Relaunch Brave:');
    console.error('  1. Quit Brave (Cmd+Q)');
    console.error('  2. Run: open -a "Brave Browser" --args --remote-debugging-port=9222');
    process.exit(1);
  }

  // Open new tab for ChatGPT
  const page = await browser.newPage();

  try {
    console.error('Navigating to ChatGPT...');
    await page.goto('https://chatgpt.com/', { waitUntil: 'networkidle2', timeout: 30000 });

    // Verify we're logged in by checking for the composer
    const composerSelector = '#prompt-textarea, [id="prompt-textarea"], div[contenteditable="true"][data-placeholder]';
    try {
      await waitForSelector(page, composerSelector, 15000);
    } catch {
      // Check if login button is present
      const loginBtn = await page.$('button[data-testid="login-button"], a[href*="auth"]');
      if (loginBtn) {
        console.error('ERROR: Not logged into ChatGPT. Log in via Brave first.');
        process.exit(1);
      }
      console.error('ERROR: Could not find ChatGPT composer. The UI may have changed.');
      process.exit(1);
    }

    console.error('Logged in. Sending prompt...');

    // Find and focus the composer
    const composer = await page.$(composerSelector);
    await composer.click();

    // Type the prompt — use clipboard for large prompts
    await page.evaluate(async (text) => {
      const composer = document.querySelector('#prompt-textarea, [id="prompt-textarea"], div[contenteditable="true"][data-placeholder]');
      if (composer) {
        // Use execCommand for contenteditable divs
        composer.focus();
        // Clear existing content
        document.execCommand('selectAll', false, null);
        // Insert via clipboard API for reliability with large text
        const clipItem = new ClipboardItem({
          'text/plain': new Blob([text], { type: 'text/plain' })
        });
        await navigator.clipboard.write([clipItem]);
        document.execCommand('paste');
      }
    }, prompt);

    // Small delay to ensure content is rendered
    await new Promise(r => setTimeout(r, 500));

    // Verify content was entered
    const composerText = await page.evaluate(() => {
      const el = document.querySelector('#prompt-textarea, [id="prompt-textarea"], div[contenteditable="true"][data-placeholder]');
      return el ? el.textContent.length : 0;
    });

    if (composerText < 10) {
      // Fallback: type directly (slower but more reliable)
      console.error('Clipboard paste failed, typing directly...');
      await composer.click({ clickCount: 3 }); // select all
      await page.keyboard.type(prompt, { delay: 1 });
    }

    // Find and click the send button
    const sendSelector = 'button[data-testid="send-button"], button[aria-label="Send prompt"], button[aria-label*="Send"]';
    const sendBtn = await page.$(sendSelector);
    if (sendBtn) {
      await sendBtn.click();
    } else {
      // Fallback: press Enter
      await page.keyboard.press('Enter');
    }

    console.error('Prompt sent. Waiting for response...');

    // Wait for the response to complete
    // Strategy: watch for the stop button to appear then disappear
    const stopSelector = 'button[data-testid="stop-button"], button[aria-label="Stop generating"], button[aria-label*="Stop"]';

    // Wait for generation to start (stop button appears)
    try {
      await waitForSelector(page, stopSelector, 30000);
      console.error('Generating...');
    } catch {
      // Stop button might not appear for very fast responses
      console.error('Response may have completed quickly.');
    }

    // Wait for generation to finish (stop button disappears)
    await page.waitForFunction(
      (sel) => !document.querySelector(sel),
      { timeout: timeoutMs, polling: 1000 },
      stopSelector
    );

    // Small delay for final rendering
    await new Promise(r => setTimeout(r, 2000));

    console.error('Response complete. Extracting...');

    // Extract the last assistant message
    const response = await page.evaluate(() => {
      // ChatGPT renders assistant messages in article elements or divs with specific data attributes
      const messages = document.querySelectorAll(
        '[data-message-author-role="assistant"], article[data-testid*="conversation-turn"]'
      );
      if (messages.length === 0) return null;

      const lastMessage = messages[messages.length - 1];

      // Try to get markdown content via the copy button's data
      // Fallback to innerText
      const markdownEl = lastMessage.querySelector('.markdown, .prose');
      if (markdownEl) return markdownEl.innerText;
      return lastMessage.innerText;
    });

    if (!response) {
      console.error('ERROR: Could not extract response from page.');
      process.exit(1);
    }

    writeFileSync(outputFile, response, 'utf-8');
    console.error(`Response saved to: ${outputFile} (${response.length} chars)`);

  } finally {
    // Close the tab we opened, don't close the browser
    await page.close();
    browser.disconnect();
  }
}

main().catch(err => {
  console.error(`Fatal: ${err.message}`);
  process.exit(1);
});
